mlola-ui 1.1.10 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlola-ui",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "mcpName": "io.github.mlolahq/mlola-ui",
5
5
  "description": "Source-copy CLI that writes framework-free Mlola UI items into your project",
6
6
  "type": "module",
@@ -202,6 +202,7 @@ correct. This table is read out of the stylesheet, so it is never stale.
202
202
  | `.ml-dropdown-item` | `data-danger` | _presence only_ |
203
203
  | `.ml-dropdown-item` | `data-highlighted` | _presence only_ |
204
204
  | `.ml-dropdown-menu` | `data-align` | `end` |
205
+ | `.ml-dropdown-menu` | `data-side` | `top` |
205
206
  | `.ml-dropdown-trigger` | `aria-expanded` | `true` |
206
207
  | `.ml-dropzone` | `aria-disabled` | _presence only_ |
207
208
  | `.ml-dropzone` | `data-dragging` | _presence only_ |
@@ -689,6 +689,9 @@
689
689
  "ml-dropdown-menu": {
690
690
  "data-align": [
691
691
  "end"
692
+ ],
693
+ "data-side": [
694
+ "top"
692
695
  ]
693
696
  },
694
697
  "ml-dropdown-trigger": {
@@ -582,6 +582,9 @@
582
582
  "attributes": {
583
583
  "data-align": [
584
584
  "end"
585
+ ],
586
+ "data-side": [
587
+ "top"
585
588
  ]
586
589
  }
587
590
  },
@@ -2,7 +2,7 @@
2
2
  "$schema": "./schema/registry-index.schema.json",
3
3
  "schemaVersion": 2,
4
4
  "name": "mlola-ui",
5
- "version": "1.1.10",
5
+ "version": "1.1.12",
6
6
  "homepage": "https://ui.mlola.com",
7
7
  "themeContract": {
8
8
  "attribute": "data-theme",
@@ -177,8 +177,8 @@
177
177
  },
178
178
  "registryDependencies": [],
179
179
  "engineDependencies": {
180
- "@mlola-ui/behavior": "^1.1.10",
181
- "@mlola-ui/icons": "^1.1.10"
180
+ "@mlola-ui/behavior": "^1.1.12",
181
+ "@mlola-ui/icons": "^1.1.12"
182
182
  },
183
183
  "options": [
184
184
  {
@@ -239,7 +239,7 @@
239
239
  },
240
240
  "registryDependencies": [],
241
241
  "engineDependencies": {
242
- "@mlola-ui/icons": "^1.1.10"
242
+ "@mlola-ui/icons": "^1.1.12"
243
243
  },
244
244
  "options": [
245
245
  {
@@ -401,7 +401,7 @@
401
401
  },
402
402
  "registryDependencies": [],
403
403
  "engineDependencies": {
404
- "@mlola-ui/icons": "^1.1.10"
404
+ "@mlola-ui/icons": "^1.1.12"
405
405
  },
406
406
  "options": [
407
407
  {
@@ -493,7 +493,7 @@
493
493
  },
494
494
  "registryDependencies": [],
495
495
  "engineDependencies": {
496
- "@mlola-ui/icons": "^1.1.10"
496
+ "@mlola-ui/icons": "^1.1.12"
497
497
  },
498
498
  "options": [],
499
499
  "variants": [],
@@ -546,7 +546,7 @@
546
546
  "spinner"
547
547
  ],
548
548
  "engineDependencies": {
549
- "@mlola-ui/motion": "^1.1.10"
549
+ "@mlola-ui/motion": "^1.1.12"
550
550
  },
551
551
  "options": [
552
552
  {
@@ -713,8 +713,8 @@
713
713
  },
714
714
  "registryDependencies": [],
715
715
  "engineDependencies": {
716
- "@mlola-ui/behavior": "^1.1.10",
717
- "@mlola-ui/icons": "^1.1.10"
716
+ "@mlola-ui/behavior": "^1.1.12",
717
+ "@mlola-ui/icons": "^1.1.12"
718
718
  },
719
719
  "options": [
720
720
  {
@@ -782,7 +782,7 @@
782
782
  },
783
783
  "registryDependencies": [],
784
784
  "engineDependencies": {
785
- "@mlola-ui/icons": "^1.1.10"
785
+ "@mlola-ui/icons": "^1.1.12"
786
786
  },
787
787
  "options": [],
788
788
  "variants": [],
@@ -837,7 +837,7 @@
837
837
  "modal"
838
838
  ],
839
839
  "engineDependencies": {
840
- "@mlola-ui/icons": "^1.1.10"
840
+ "@mlola-ui/icons": "^1.1.12"
841
841
  },
842
842
  "options": [],
843
843
  "variants": [],
@@ -900,8 +900,8 @@
900
900
  },
901
901
  "registryDependencies": [],
902
902
  "engineDependencies": {
903
- "@mlola-ui/behavior": "^1.1.10",
904
- "@mlola-ui/icons": "^1.1.10"
903
+ "@mlola-ui/behavior": "^1.1.12",
904
+ "@mlola-ui/icons": "^1.1.12"
905
905
  },
906
906
  "options": [
907
907
  {
@@ -927,7 +927,7 @@
927
927
  "path": "packages/components/dropdown-menu/dropdown-menu.tsx",
928
928
  "target": "{{aliases.components}}/dropdown-menu.tsx",
929
929
  "type": "registry:ui",
930
- "integrity": "sha256-xgybCu9HBxIieafu5CjAtY4aCOQoaAj/VUCH6D6vLP8="
930
+ "integrity": "sha256-kafvzv+Kc9MKJqXteEIUwvYvSD+npDrOyvthc5+L2ck="
931
931
  }
932
932
  ],
933
933
  "themeContract": {
@@ -965,7 +965,7 @@
965
965
  "input"
966
966
  ],
967
967
  "engineDependencies": {
968
- "@mlola-ui/icons": "^1.1.10"
968
+ "@mlola-ui/icons": "^1.1.12"
969
969
  },
970
970
  "options": [],
971
971
  "variants": [],
@@ -1189,8 +1189,8 @@
1189
1189
  },
1190
1190
  "registryDependencies": [],
1191
1191
  "engineDependencies": {
1192
- "@mlola-ui/behavior": "^1.1.10",
1193
- "@mlola-ui/icons": "^1.1.10"
1192
+ "@mlola-ui/behavior": "^1.1.12",
1193
+ "@mlola-ui/icons": "^1.1.12"
1194
1194
  },
1195
1195
  "options": [
1196
1196
  {
@@ -1219,7 +1219,7 @@
1219
1219
  "path": "packages/components/_internal/anchor.ts",
1220
1220
  "target": "{{aliases.components}}/_internal/anchor.ts",
1221
1221
  "type": "registry:ui",
1222
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
1222
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
1223
1223
  },
1224
1224
  {
1225
1225
  "path": "packages/components/_internal/dialog.ts",
@@ -1340,7 +1340,7 @@
1340
1340
  },
1341
1341
  "registryDependencies": [],
1342
1342
  "engineDependencies": {
1343
- "@mlola-ui/icons": "^1.1.10"
1343
+ "@mlola-ui/icons": "^1.1.12"
1344
1344
  },
1345
1345
  "options": [],
1346
1346
  "variants": [],
@@ -1391,7 +1391,7 @@
1391
1391
  },
1392
1392
  "registryDependencies": [],
1393
1393
  "engineDependencies": {
1394
- "@mlola-ui/behavior": "^1.1.10"
1394
+ "@mlola-ui/behavior": "^1.1.12"
1395
1395
  },
1396
1396
  "options": [
1397
1397
  {
@@ -1423,7 +1423,7 @@
1423
1423
  "path": "packages/components/_internal/anchor.ts",
1424
1424
  "target": "{{aliases.components}}/_internal/anchor.ts",
1425
1425
  "type": "registry:ui",
1426
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
1426
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
1427
1427
  },
1428
1428
  {
1429
1429
  "path": "packages/components/_internal/floating.ts",
@@ -1766,7 +1766,7 @@
1766
1766
  },
1767
1767
  "registryDependencies": [],
1768
1768
  "engineDependencies": {
1769
- "@mlola-ui/behavior": "^1.1.10"
1769
+ "@mlola-ui/behavior": "^1.1.12"
1770
1770
  },
1771
1771
  "options": [],
1772
1772
  "variants": [],
@@ -1819,8 +1819,8 @@
1819
1819
  "input"
1820
1820
  ],
1821
1821
  "engineDependencies": {
1822
- "@mlola-ui/behavior": "^1.1.10",
1823
- "@mlola-ui/icons": "^1.1.10"
1822
+ "@mlola-ui/behavior": "^1.1.12",
1823
+ "@mlola-ui/icons": "^1.1.12"
1824
1824
  },
1825
1825
  "options": [
1826
1826
  {
@@ -1844,7 +1844,7 @@
1844
1844
  "path": "packages/components/_internal/anchor.ts",
1845
1845
  "target": "{{aliases.components}}/_internal/anchor.ts",
1846
1846
  "type": "registry:ui",
1847
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
1847
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
1848
1848
  },
1849
1849
  {
1850
1850
  "path": "packages/components/_internal/floating.ts",
@@ -1897,8 +1897,8 @@
1897
1897
  },
1898
1898
  "registryDependencies": [],
1899
1899
  "engineDependencies": {
1900
- "@mlola-ui/behavior": "^1.1.10",
1901
- "@mlola-ui/icons": "^1.1.10"
1900
+ "@mlola-ui/behavior": "^1.1.12",
1901
+ "@mlola-ui/icons": "^1.1.12"
1902
1902
  },
1903
1903
  "options": [
1904
1904
  {
@@ -1934,7 +1934,7 @@
1934
1934
  "path": "packages/components/_internal/anchor.ts",
1935
1935
  "target": "{{aliases.components}}/_internal/anchor.ts",
1936
1936
  "type": "registry:ui",
1937
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
1937
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
1938
1938
  },
1939
1939
  {
1940
1940
  "path": "packages/components/_internal/dialog.ts",
@@ -2044,7 +2044,7 @@
2044
2044
  "input"
2045
2045
  ],
2046
2046
  "engineDependencies": {
2047
- "@mlola-ui/behavior": "^1.1.10"
2047
+ "@mlola-ui/behavior": "^1.1.12"
2048
2048
  },
2049
2049
  "options": [
2050
2050
  {
@@ -2189,7 +2189,7 @@
2189
2189
  },
2190
2190
  "registryDependencies": [],
2191
2191
  "engineDependencies": {
2192
- "@mlola-ui/behavior": "^1.1.10"
2192
+ "@mlola-ui/behavior": "^1.1.12"
2193
2193
  },
2194
2194
  "options": [
2195
2195
  {
@@ -2321,7 +2321,7 @@
2321
2321
  },
2322
2322
  "registryDependencies": [],
2323
2323
  "engineDependencies": {
2324
- "@mlola-ui/icons": "^1.1.10"
2324
+ "@mlola-ui/icons": "^1.1.12"
2325
2325
  },
2326
2326
  "options": [
2327
2327
  {
@@ -2407,7 +2407,7 @@
2407
2407
  "spinner"
2408
2408
  ],
2409
2409
  "engineDependencies": {
2410
- "@mlola-ui/icons": "^1.1.10"
2410
+ "@mlola-ui/icons": "^1.1.12"
2411
2411
  },
2412
2412
  "options": [
2413
2413
  {
@@ -2550,7 +2550,7 @@
2550
2550
  },
2551
2551
  "registryDependencies": [],
2552
2552
  "engineDependencies": {
2553
- "@mlola-ui/behavior": "^1.1.10"
2553
+ "@mlola-ui/behavior": "^1.1.12"
2554
2554
  },
2555
2555
  "options": [
2556
2556
  {
@@ -2572,7 +2572,7 @@
2572
2572
  "path": "packages/components/_internal/anchor.ts",
2573
2573
  "target": "{{aliases.components}}/_internal/anchor.ts",
2574
2574
  "type": "registry:ui",
2575
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
2575
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
2576
2576
  },
2577
2577
  {
2578
2578
  "path": "packages/components/_internal/react.ts",
@@ -2689,7 +2689,7 @@
2689
2689
  },
2690
2690
  "registryDependencies": [],
2691
2691
  "engineDependencies": {
2692
- "@mlola-ui/icons": "^1.1.10"
2692
+ "@mlola-ui/icons": "^1.1.12"
2693
2693
  },
2694
2694
  "options": [
2695
2695
  {
@@ -2761,7 +2761,7 @@
2761
2761
  "popover"
2762
2762
  ],
2763
2763
  "engineDependencies": {
2764
- "@mlola-ui/icons": "^1.1.10"
2764
+ "@mlola-ui/icons": "^1.1.12"
2765
2765
  },
2766
2766
  "options": [
2767
2767
  {
@@ -2831,7 +2831,7 @@
2831
2831
  "popover"
2832
2832
  ],
2833
2833
  "engineDependencies": {
2834
- "@mlola-ui/icons": "^1.1.10"
2834
+ "@mlola-ui/icons": "^1.1.12"
2835
2835
  },
2836
2836
  "options": [],
2837
2837
  "variants": [],
@@ -3029,7 +3029,7 @@
3029
3029
  "input"
3030
3030
  ],
3031
3031
  "engineDependencies": {
3032
- "@mlola-ui/icons": "^1.1.10"
3032
+ "@mlola-ui/icons": "^1.1.12"
3033
3033
  },
3034
3034
  "options": [
3035
3035
  {
@@ -3106,7 +3106,7 @@
3106
3106
  "input"
3107
3107
  ],
3108
3108
  "engineDependencies": {
3109
- "@mlola-ui/icons": "^1.1.10"
3109
+ "@mlola-ui/icons": "^1.1.12"
3110
3110
  },
3111
3111
  "options": [],
3112
3112
  "variants": [],
@@ -3161,7 +3161,7 @@
3161
3161
  "input"
3162
3162
  ],
3163
3163
  "engineDependencies": {
3164
- "@mlola-ui/icons": "^1.1.10"
3164
+ "@mlola-ui/icons": "^1.1.12"
3165
3165
  },
3166
3166
  "options": [],
3167
3167
  "variants": [],
@@ -3224,7 +3224,7 @@
3224
3224
  "popover"
3225
3225
  ],
3226
3226
  "engineDependencies": {
3227
- "@mlola-ui/icons": "^1.1.10"
3227
+ "@mlola-ui/icons": "^1.1.12"
3228
3228
  },
3229
3229
  "options": [
3230
3230
  {
@@ -3294,7 +3294,7 @@
3294
3294
  },
3295
3295
  "registryDependencies": [],
3296
3296
  "engineDependencies": {
3297
- "@mlola-ui/icons": "^1.1.10"
3297
+ "@mlola-ui/icons": "^1.1.12"
3298
3298
  },
3299
3299
  "options": [
3300
3300
  {
@@ -3413,8 +3413,8 @@
3413
3413
  },
3414
3414
  "registryDependencies": [],
3415
3415
  "engineDependencies": {
3416
- "@mlola-ui/behavior": "^1.1.10",
3417
- "@mlola-ui/icons": "^1.1.10"
3416
+ "@mlola-ui/behavior": "^1.1.12",
3417
+ "@mlola-ui/icons": "^1.1.12"
3418
3418
  },
3419
3419
  "options": [],
3420
3420
  "variants": [],
@@ -3424,7 +3424,7 @@
3424
3424
  "path": "packages/components/_internal/anchor.ts",
3425
3425
  "target": "{{aliases.components}}/_internal/anchor.ts",
3426
3426
  "type": "registry:ui",
3427
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
3427
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
3428
3428
  },
3429
3429
  {
3430
3430
  "path": "packages/components/_internal/floating.ts",
@@ -3478,7 +3478,7 @@
3478
3478
  },
3479
3479
  "registryDependencies": [],
3480
3480
  "engineDependencies": {
3481
- "@mlola-ui/behavior": "^1.1.10"
3481
+ "@mlola-ui/behavior": "^1.1.12"
3482
3482
  },
3483
3483
  "options": [
3484
3484
  {
@@ -3510,7 +3510,7 @@
3510
3510
  "path": "packages/components/_internal/anchor.ts",
3511
3511
  "target": "{{aliases.components}}/_internal/anchor.ts",
3512
3512
  "type": "registry:ui",
3513
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
3513
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
3514
3514
  },
3515
3515
  {
3516
3516
  "path": "packages/components/_internal/floating.ts",
@@ -3565,8 +3565,8 @@
3565
3565
  },
3566
3566
  "registryDependencies": [],
3567
3567
  "engineDependencies": {
3568
- "@mlola-ui/behavior": "^1.1.10",
3569
- "@mlola-ui/icons": "^1.1.10"
3568
+ "@mlola-ui/behavior": "^1.1.12",
3569
+ "@mlola-ui/icons": "^1.1.12"
3570
3570
  },
3571
3571
  "options": [],
3572
3572
  "variants": [],
@@ -3576,7 +3576,7 @@
3576
3576
  "path": "packages/components/_internal/anchor.ts",
3577
3577
  "target": "{{aliases.components}}/_internal/anchor.ts",
3578
3578
  "type": "registry:ui",
3579
- "integrity": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8="
3579
+ "integrity": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w="
3580
3580
  },
3581
3581
  {
3582
3582
  "path": "packages/components/_internal/floating.ts",
@@ -3640,7 +3640,7 @@
3640
3640
  "sheet"
3641
3641
  ],
3642
3642
  "engineDependencies": {
3643
- "@mlola-ui/icons": "^1.1.10"
3643
+ "@mlola-ui/icons": "^1.1.12"
3644
3644
  },
3645
3645
  "options": [],
3646
3646
  "variants": [],
@@ -3763,7 +3763,7 @@
3763
3763
  "button"
3764
3764
  ],
3765
3765
  "engineDependencies": {
3766
- "@mlola-ui/icons": "^1.1.10"
3766
+ "@mlola-ui/icons": "^1.1.12"
3767
3767
  },
3768
3768
  "options": [
3769
3769
  {
@@ -3866,8 +3866,8 @@
3866
3866
  "input"
3867
3867
  ],
3868
3868
  "engineDependencies": {
3869
- "@mlola-ui/behavior": "^1.1.10",
3870
- "@mlola-ui/icons": "^1.1.10"
3869
+ "@mlola-ui/behavior": "^1.1.12",
3870
+ "@mlola-ui/icons": "^1.1.12"
3871
3871
  },
3872
3872
  "options": [
3873
3873
  {
@@ -2,4 +2,4 @@
2
2
  * Where a floating layer goes next to its anchor. The math is shared with the
3
3
  * framework-free runtime, so it lives in @mlola-ui/behavior/logic.
4
4
  */
5
- export { fitTooltip, placeFloating, type Align, type Placement, type Rect, type Side } from "@mlola-ui/behavior/logic";
5
+ export { fitMenu, fitTooltip, placeFloating, type Align, type Placement, type Rect, type Side } from "@mlola-ui/behavior/logic";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import * as React from "react";
4
- import { rovingIndex } from "@mlola-ui/behavior/logic";
4
+ import { fitMenu, rovingIndex } from "@mlola-ui/behavior/logic";
5
5
  import { composeRefs, cx } from "../_internal/react";
6
6
  import { IconChevronDown } from "@mlola-ui/icons";
7
7
 
@@ -29,6 +29,7 @@ const DropdownMenu = React.forwardRef<HTMLDivElement, DropdownMenuProps>(
29
29
  const [activeIndex, setActiveIndex] = React.useState(-1);
30
30
  const rootRef = React.useRef<HTMLDivElement>(null);
31
31
  const triggerRef = React.useRef<HTMLButtonElement>(null);
32
+ const menuRef = React.useRef<HTMLDivElement>(null);
32
33
  const itemRefs = React.useRef<Array<HTMLButtonElement | null>>([]);
33
34
  const enabled = React.useMemo(
34
35
  () => items.map((item, index) => item.disabled ? -1 : index).filter((index) => index >= 0),
@@ -64,6 +65,27 @@ const DropdownMenu = React.forwardRef<HTMLDivElement, DropdownMenuProps>(
64
65
  if (target >= 0) focus(target);
65
66
  };
66
67
 
68
+ // CSS hangs the menu under the trigger; this keeps it on screen, the same way the framework-free runtime does.
69
+ React.useLayoutEffect(() => {
70
+ const menu = menuRef.current;
71
+ const root = rootRef.current;
72
+ if (!open || !menu || !root) return;
73
+ const fit = () => {
74
+ const rect = root.getBoundingClientRect();
75
+ const { side, shift } = fitMenu(
76
+ { x: rect.left, y: rect.top, width: rect.width, height: rect.height },
77
+ { width: menu.offsetWidth, height: menu.offsetHeight },
78
+ { width: window.innerWidth, height: window.innerHeight },
79
+ align,
80
+ );
81
+ menu.style.setProperty("--ml-dropdown-shift", `${shift}px`);
82
+ menu.setAttribute("data-side", side);
83
+ };
84
+ fit();
85
+ window.addEventListener("resize", fit);
86
+ return () => window.removeEventListener("resize", fit);
87
+ }, [align, open]);
88
+
67
89
  React.useEffect(() => {
68
90
  if (!open) return;
69
91
  const onPointerDown = (event: MouseEvent) => {
@@ -99,6 +121,7 @@ const DropdownMenu = React.forwardRef<HTMLDivElement, DropdownMenuProps>(
99
121
  </button>
100
122
  {open ? (
101
123
  <div
124
+ ref={menuRef}
102
125
  role="menu"
103
126
  aria-label={label}
104
127
  data-align={align}
@@ -1,5 +1,5 @@
1
1
  {
2
- "packages/components/_internal/anchor.ts": "sha256-/yW3RVjoY6QfTWnUYSeZ9rFkC9W4WGB1qop8Jp/H1r8=",
2
+ "packages/components/_internal/anchor.ts": "sha256-Z/JqFS7yiQHgVMqUVu+Lr5qnqIzIxRFs+Zuq7r/iU7w=",
3
3
  "packages/components/_internal/clipboard.ts": "sha256-0y5p88CTXWuOrUYlC5J4XP1VCrOwkx9jYWVHmD2LouQ=",
4
4
  "packages/components/_internal/dialog.ts": "sha256-dfOsfaszM/rhBJXvl7vtM4Vdh7SGflY5Capi1YoY6ow=",
5
5
  "packages/components/_internal/dom.ts": "sha256-TJp94MipbXHonH/PC7FFHu5pnAqcoxzLocksWLsTAsc=",
@@ -29,7 +29,7 @@
29
29
  "packages/components/context-menu/context-menu.tsx": "sha256-OGaKzthZJGaV5T+4sRWYecA64wEEg2KImKnIzMMg1i4=",
30
30
  "packages/components/copy-button/copy-button.tsx": "sha256-6fvfifoiDOtW+WxKWon4SGEn3THtERuCX2hqGSZDtVM=",
31
31
  "packages/components/date-picker/date-picker.tsx": "sha256-QABmZzPKHc706/Rs+ln3ifDK3T2lXl34rehhuRXW+8o=",
32
- "packages/components/dropdown-menu/dropdown-menu.tsx": "sha256-xgybCu9HBxIieafu5CjAtY4aCOQoaAj/VUCH6D6vLP8=",
32
+ "packages/components/dropdown-menu/dropdown-menu.tsx": "sha256-kafvzv+Kc9MKJqXteEIUwvYvSD+npDrOyvthc5+L2ck=",
33
33
  "packages/components/dropzone/dropzone.tsx": "sha256-tHCCpEWE6839UeLOszTo+R2vAL4Sp9UxuRdLkFLfnq4=",
34
34
  "packages/components/empty-state/empty-state.tsx": "sha256-/phk3A6TDaiqo61fCcAc/4Bi85e1yBGAtKXFaGhrjyw=",
35
35
  "packages/components/hover-card/hover-card.tsx": "sha256-Bu5m03mFjiM7x38U1aSrcb9Th8RLYozyjwW/Cu3knlk=",
package/src/knowledge.js CHANGED
@@ -200,7 +200,9 @@ function tagsOf(markup) {
200
200
  const attributes = new Map();
201
201
  for (const attribute of match[2].matchAll(/([^\s"'>={}]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\{(?:[^{}]|\{[^{}]*\})*\})))?/g)) {
202
202
  const [, name, double, single, expression] = attribute;
203
- const value = double ?? single ?? (expression ? /^\{\s*["'`]([^"'`$]*)["'`]\s*\}$/.exec(expression)?.[1] ?? null : "");
203
+ let value = double ?? single ?? (expression ? /^\{\s*["'`]([^"'`$]*)["'`]\s*\}$/.exec(expression)?.[1] ?? null : "");
204
+ // Markup built in a script string ('<span data-tone="' + tone + '">') is only known at runtime.
205
+ if (typeof value === "string" && /['"`]\s*\+|\+\s*['"`]|\$\{/.test(value)) value = null;
204
206
  attributes.set(name, value);
205
207
  if (expression) attributes.set(`${name}:raw`, expression);
206
208
  }
@@ -323,6 +325,8 @@ export function checkMarkup(markup) {
323
325
  const open = rule.lastIndexOf("{");
324
326
  if (open < 0) continue;
325
327
  const selector = rule.slice(0, open).split("{").pop().trim();
328
+ // A keyframe (from, to, 50%) is a step of an animation, not a rule for text at rest.
329
+ if (/^(from|to|\d+(\.\d+)?%)(\s*,\s*(from|to|\d+(\.\d+)?%))*$/i.test(selector)) continue;
326
330
  const body = rule.slice(open + 1).replace(/url\([^)]*\)/g, "");
327
331
  const where = `<style> ${selector}`;
328
332
  const overridden = [...body.matchAll(/(--ml-[\w-]+)\s*:/g)].map((match) => match[1]).filter((token) => tokenNames.has(token));
@@ -333,8 +337,9 @@ export function checkMarkup(markup) {
333
337
  note("error", where, `${overridden.join(", ")} is a theme token; setting it here overrides the theme.`, "Pick a theme, or change the theme's spec (mlola.theme.json), instead of redefining its tokens.");
334
338
  }
335
339
  // Faded text: its contrast now depends on the theme behind it.
336
- const opacity = /(?:^|;)\s*opacity\s*:\s*(0?\.\d+|0)\s*(?:;|$)/.exec(body);
337
- if (opacity && !/disabled|:empty|::?placeholder|\[hidden\]|inert/.test(selector)) {
340
+ // opacity: 0 hides; only a value between 0 and 1 fades what is still read.
341
+ const opacity = /(?:^|;)\s*opacity\s*:\s*(0?\.\d+)\s*(?:;|$)/.exec(body);
342
+ if (opacity && Number(opacity[1]) > 0 && !/disabled|:empty|::?placeholder|\[hidden\]|inert/.test(selector)) {
338
343
  note("warning", where, `opacity: ${opacity[1]} fades whatever text is inside, and how far it falls below the contrast floor depends on the theme and the fill behind it.`, "For quieter text use color: var(--ml-text-muted); on a filled control, its -foreground role. Keep opacity for disabled or decorative parts.");
339
344
  }
340
345
  }