Skip to content

Commit cd2b549

Browse files
committed
fix(tasty): selector generation
1 parent 60649d3 commit cd2b549

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

src/components/overlays/Modal/Modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const ModalElement = tasty({
5959
transform: {
6060
'': 'initial',
6161
'type=modal & !open': 'translate(0, -3x) scale(1, 1)',
62-
'([data-type^="fullscreen"] | type=panel) & !open':
62+
'(type^=fullscreen | type=panel) & !open':
6363
'translate(0, 0) scale(1.02, 1.02)',
6464
},
6565
opacity: {

src/tasty/utils/styles.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,15 @@ export function getModSelector(modName: string): string {
120120
if (!MOD_NAME_CACHE.has(modName)) {
121121
let selector: string;
122122

123-
// Check if it's a shorthand value mod: key=value, key="value", or key='value'
124-
const valueModMatch = modName.match(/^([a-z][a-z0-9-]*)=(.+)$/i);
123+
// Check if it's a shorthand value mod: key=value, key^=value, key$=value, key*=value
124+
// Supports: key=value, key="value", key='value', and with ^=, $=, *= operators
125+
const valueModMatch = modName.match(
126+
/^([a-z][a-z0-9-]*)(\^=|\$=|\*=|=)(.+)$/i,
127+
);
125128
if (valueModMatch) {
126129
const key = valueModMatch[1];
127-
let value = valueModMatch[2];
130+
const operator = valueModMatch[2];
131+
let value = valueModMatch[3];
128132

129133
// Remove quotes if present
130134
if (
@@ -134,8 +138,8 @@ export function getModSelector(modName: string): string {
134138
value = value.slice(1, -1);
135139
}
136140

137-
// Convert to full attribute selector
138-
selector = `[data-${camelToKebab(key)}="${value}"]`;
141+
// Convert to full attribute selector with the appropriate operator
142+
selector = `[data-${camelToKebab(key)}${operator}"${value}"]`;
139143
} else if (modName.match(/^[a-z]/)) {
140144
// Boolean mod: convert camelCase to kebab-case
141145
selector = `[data-${camelToKebab(modName)}]`;

src/tasty/value-mods.test.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,40 @@ describe('Value Mods', () => {
492492

493493
consoleErrorSpy.mockRestore();
494494
});
495+
496+
it('should transform type^=fullscreen to [data-type^="fullscreen"]', () => {
497+
expect(getModSelector('type^=fullscreen')).toBe(
498+
'[data-type^="fullscreen"]',
499+
);
500+
});
501+
502+
it('should transform type$=screen to [data-type$="screen"]', () => {
503+
expect(getModSelector('type$=screen')).toBe('[data-type$="screen"]');
504+
});
505+
506+
it('should transform type*=full to [data-type*="full"]', () => {
507+
expect(getModSelector('type*=full')).toBe('[data-type*="full"]');
508+
});
509+
510+
it('should handle quoted values with ^= operator', () => {
511+
expect(getModSelector('type^="fullscreen"')).toBe(
512+
'[data-type^="fullscreen"]',
513+
);
514+
});
515+
516+
it('should handle single-quoted values with $= operator', () => {
517+
expect(getModSelector("type$='screen'")).toBe('[data-type$="screen"]');
518+
});
519+
520+
it('should handle quoted values with *= operator', () => {
521+
expect(getModSelector('name*="test"')).toBe('[data-name*="test"]');
522+
});
523+
524+
it('should convert camelCase keys with operators', () => {
525+
expect(getModSelector('dataType^=fullscreen')).toBe(
526+
'[data-data-type^="fullscreen"]',
527+
);
528+
});
495529
});
496530

497531
it('should transform :has(Item) to :has([data-element="Item"]) in component', () => {

0 commit comments

Comments
 (0)