@enigmax/primitives 0.25.0 → 0.27.0

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.
Files changed (55) hide show
  1. package/dist/chunk-2RIO4VDV.js +121 -0
  2. package/dist/{chunk-DZMHY3SU.js → chunk-CPJJ3FPW.js} +17 -7
  3. package/dist/chunk-EYZ366LP.js +189 -0
  4. package/dist/chunk-HUUINHPR.js +135 -0
  5. package/dist/chunk-JLZDS6CV.js +177 -0
  6. package/dist/chunk-O2UJ5ZIX.js +387 -0
  7. package/dist/chunk-PVDU6AZU.js +953 -0
  8. package/dist/{chunk-Z3VDE7OA.js → chunk-YQV5XZIA.js} +2 -2
  9. package/dist/clipboard-menu-eemzEBqB.d.ts +93 -0
  10. package/dist/context-DR1dpO8b.d.ts +54 -0
  11. package/dist/{clipboard-menu-B_ouitfS.d.ts → context-menu-qqpGBkny.d.ts} +7 -91
  12. package/dist/index.d.ts +292 -2
  13. package/dist/index.js +5 -3
  14. package/dist/menu-52PXC5PL.js +33 -0
  15. package/dist/menu-YIGMPFUP.js +58 -0
  16. package/dist/next/index.d.ts +6 -2
  17. package/dist/next/index.js +12 -8
  18. package/dist/react/context-menu.d.ts +15 -55
  19. package/dist/react/context-menu.js +2 -2
  20. package/dist/react/image.d.ts +112 -0
  21. package/dist/react/image.js +3 -0
  22. package/dist/react/index.d.ts +6 -2
  23. package/dist/react/index.js +12 -8
  24. package/dist/react/input.js +1 -1
  25. package/dist/react/video.d.ts +126 -0
  26. package/dist/react/video.js +3 -0
  27. package/dist/react-router/index.d.ts +6 -2
  28. package/dist/react-router/index.js +12 -8
  29. package/dist/viewer-N5WLFB24.js +3 -0
  30. package/package.json +15 -2
  31. package/recipes/context-menu/styles.css +8 -1
  32. package/recipes/image/styles.css +182 -0
  33. package/recipes/video/styles.css +154 -0
  34. package/registry.json +486 -5
  35. package/src/core/context-menu.ts +22 -3
  36. package/src/core/image-viewer.ts +269 -0
  37. package/src/core/player.ts +345 -0
  38. package/src/index.ts +55 -0
  39. package/src/react/context-menu/root.tsx +27 -5
  40. package/src/react/context-menu/styles.ts +8 -1
  41. package/src/react/image/icons.tsx +59 -0
  42. package/src/react/image/index.tsx +185 -0
  43. package/src/react/image/menu.tsx +80 -0
  44. package/src/react/image/styles.ts +213 -0
  45. package/src/react/image/types.ts +116 -0
  46. package/src/react/image/viewer.tsx +571 -0
  47. package/src/react/index.ts +3 -0
  48. package/src/react/video/icons.tsx +135 -0
  49. package/src/react/video/index.tsx +731 -0
  50. package/src/react/video/menu.tsx +66 -0
  51. package/src/react/video/rail.tsx +99 -0
  52. package/src/react/video/styles.ts +161 -0
  53. package/src/react/video/types.ts +141 -0
  54. /package/dist/{chunk-3MGBZOAU.js → chunk-RMNXVWQ4.js} +0 -0
  55. /package/dist/{chunk-MSOCCQGH.js → chunk-T7I6WJSN.js} +0 -0
package/registry.json CHANGED
@@ -86,6 +86,7 @@
86
86
  "[data-enigma-marquee-copy]"
87
87
  ],
88
88
  "docs": "docs/notes/primitives.md#marquee",
89
+ "source": "src/core/marquee.ts",
89
90
  "recipes": [
90
91
  "tailwind",
91
92
  "css"
@@ -151,7 +152,8 @@
151
152
  ".logo-marquee[data-grabbing]",
152
153
  ".logo-marquee__item"
153
154
  ],
154
- "docs": "docs/notes/primitives.md#logo-marquee"
155
+ "docs": "docs/notes/primitives.md#logo-marquee",
156
+ "source": "recipes/logo-marquee/index.tsx"
155
157
  },
156
158
  {
157
159
  "name": "input",
@@ -392,6 +394,7 @@
392
394
  "[data-enigma-color-preset]"
393
395
  ],
394
396
  "docs": "docs/notes/primitives.md#input",
397
+ "source": "src/core/input.ts",
395
398
  "recipes": [
396
399
  "tailwind",
397
400
  "css"
@@ -460,6 +463,7 @@
460
463
  "fuse.js": "Fuzzy matching. Omit it and a built-in substring matcher is used."
461
464
  },
462
465
  "docs": "docs/notes/primitives.md#search",
466
+ "source": "src/core/search.ts",
463
467
  "recipes": [
464
468
  "tailwind"
465
469
  ],
@@ -551,7 +555,8 @@
551
555
  "[aria-busy=true]",
552
556
  "[data-enigma-button-key]"
553
557
  ],
554
- "docs": "docs/notes/primitives.md#button"
558
+ "docs": "docs/notes/primitives.md#button",
559
+ "source": "src/core/button.ts"
555
560
  },
556
561
  {
557
562
  "name": "palette",
@@ -656,6 +661,7 @@
656
661
  "[data-enigma-palette-hint]"
657
662
  ],
658
663
  "docs": "docs/notes/primitives.md#palette",
664
+ "source": "src/core/palette.ts",
659
665
  "recipes": [
660
666
  "css"
661
667
  ]
@@ -799,6 +805,7 @@
799
805
  "[data-enigma-select-empty]"
800
806
  ],
801
807
  "docs": "docs/notes/primitives.md#select",
808
+ "source": "src/core/select.ts",
802
809
  "recipes": [
803
810
  "css"
804
811
  ]
@@ -946,6 +953,7 @@
946
953
  "[data-enigma-menu-status][data-error]"
947
954
  ],
948
955
  "docs": "docs/notes/primitives.md#context-menu",
956
+ "source": "src/core/context-menu.ts",
949
957
  "recipes": [
950
958
  "css"
951
959
  ]
@@ -1019,7 +1027,8 @@
1019
1027
  "[data-enigma-selection-marquee]",
1020
1028
  "[data-enigma-selection-empty]"
1021
1029
  ],
1022
- "docs": "docs/notes/primitives.md#selection"
1030
+ "docs": "docs/notes/primitives.md#selection",
1031
+ "source": "src/core/selection.ts"
1023
1032
  },
1024
1033
  {
1025
1034
  "name": "flags",
@@ -1081,7 +1090,8 @@
1081
1090
  "[data-enigma-flag][data-flag-shape=circle]"
1082
1091
  ],
1083
1092
  "assets": "flags",
1084
- "docs": "docs/notes/primitives.md#flags"
1093
+ "docs": "docs/notes/primitives.md#flags",
1094
+ "source": "src/core/flags.ts"
1085
1095
  },
1086
1096
  {
1087
1097
  "name": "notifications",
@@ -1140,6 +1150,7 @@
1140
1150
  ],
1141
1151
  "styles": false,
1142
1152
  "docs": "docs/notes/primitives.md#notifications",
1153
+ "source": "src/core/notifications.ts",
1143
1154
  "recipes": [
1144
1155
  "tailwind"
1145
1156
  ]
@@ -1278,6 +1289,7 @@
1278
1289
  "[data-icon]"
1279
1290
  ],
1280
1291
  "docs": "docs/notes/primitives.md#toast",
1292
+ "source": "src/react/toaster.tsx",
1281
1293
  "recipes": [
1282
1294
  "tailwind",
1283
1295
  "css"
@@ -1331,7 +1343,8 @@
1331
1343
  }
1332
1344
  ],
1333
1345
  "styles": false,
1334
- "docs": "docs/notes/primitives.md#network"
1346
+ "docs": "docs/notes/primitives.md#network",
1347
+ "source": "src/core/network.ts"
1335
1348
  },
1336
1349
  {
1337
1350
  "name": "relative-time",
@@ -1399,9 +1412,477 @@
1399
1412
  "[data-relative-time-capitalize-first-letter=true]"
1400
1413
  ],
1401
1414
  "docs": "docs/notes/primitives.md#relative-time",
1415
+ "source": "src/core/relative-time.ts",
1402
1416
  "dependencies": {
1403
1417
  "@github/relative-time-element": "^4.4.0"
1404
1418
  }
1419
+ },
1420
+ {
1421
+ "name": "image",
1422
+ "title": "Image, with the viewer a press on it opens",
1423
+ "description": "An image that opens into a lightbox: a press enlarges it and the picture flies out of the page into the viewer, the wheel zooms around the cursor, with a drag to pan, a pinch on touch, and the keyboard driving all of it. Everything else is a decision about the page it sits in, so it is off until asked for - the arrows and counter of a set, the strip of previews along the bottom, a three-dot menu that downloads the file, and a discard action that drops an image and moves to the next. The viewer is its own chunk, fetched on intent, and the menu another under that, so a page of images nobody enlarges downloads neither. It brings a theme: there is no useful unstyled lightbox.",
1424
+ "targets": [
1425
+ "react"
1426
+ ],
1427
+ "entry": {
1428
+ "react": "@enigmax/primitives/react/image"
1429
+ },
1430
+ "exports": {
1431
+ "react": [
1432
+ "Image"
1433
+ ]
1434
+ },
1435
+ "files": [
1436
+ {
1437
+ "path": "src/core/image-viewer.ts",
1438
+ "dest": "image/image-viewer.ts",
1439
+ "targets": [
1440
+ "react"
1441
+ ]
1442
+ },
1443
+ {
1444
+ "path": "src/core/context-menu.ts",
1445
+ "dest": "image/context-menu.ts",
1446
+ "targets": [
1447
+ "react"
1448
+ ],
1449
+ "rewrite": {
1450
+ "@/core/search": "./search-core",
1451
+ "@/core/keys": "./keys"
1452
+ }
1453
+ },
1454
+ {
1455
+ "path": "src/core/search.ts",
1456
+ "dest": "image/search-core.ts",
1457
+ "targets": [
1458
+ "react"
1459
+ ]
1460
+ },
1461
+ {
1462
+ "path": "src/core/keys.ts",
1463
+ "dest": "image/keys.ts",
1464
+ "targets": [
1465
+ "react"
1466
+ ]
1467
+ },
1468
+ {
1469
+ "path": "src/react/image/types.ts",
1470
+ "dest": "image/types.ts",
1471
+ "targets": [
1472
+ "react"
1473
+ ],
1474
+ "rewrite": {
1475
+ "@/react/context-menu/context": "./context"
1476
+ }
1477
+ },
1478
+ {
1479
+ "path": "src/react/image/icons.tsx",
1480
+ "dest": "image/icons.tsx",
1481
+ "targets": [
1482
+ "react"
1483
+ ]
1484
+ },
1485
+ {
1486
+ "path": "src/react/image/styles.ts",
1487
+ "dest": "image/styles.ts",
1488
+ "targets": [
1489
+ "react"
1490
+ ]
1491
+ },
1492
+ {
1493
+ "path": "src/core/clipboard-menu.ts",
1494
+ "dest": "image/clipboard-menu.ts",
1495
+ "targets": [
1496
+ "react"
1497
+ ],
1498
+ "rewrite": {
1499
+ "@/core/context-menu": "./context-menu",
1500
+ "@/react/context-menu/styles": "./context-menu-styles"
1501
+ }
1502
+ },
1503
+ {
1504
+ "path": "src/react/slot.tsx",
1505
+ "dest": "image/slot.tsx",
1506
+ "targets": [
1507
+ "react"
1508
+ ],
1509
+ "rewrite": {
1510
+ "@/react/context-menu/styles": "./context-menu-styles"
1511
+ }
1512
+ },
1513
+ {
1514
+ "path": "src/react/context-menu/styles.ts",
1515
+ "dest": "image/context-menu-styles.ts",
1516
+ "targets": [
1517
+ "react"
1518
+ ],
1519
+ "rewrite": {
1520
+ "@/react/context-menu/styles": "./context-menu-styles"
1521
+ }
1522
+ },
1523
+ {
1524
+ "path": "recipes/context-menu/styles.css",
1525
+ "dest": "image/context-menu-styles.css",
1526
+ "targets": [
1527
+ "react"
1528
+ ],
1529
+ "style": "css",
1530
+ "rewrite": {
1531
+ "@/react/context-menu/styles": "./context-menu-styles"
1532
+ }
1533
+ },
1534
+ {
1535
+ "path": "src/react/context-menu/context.ts",
1536
+ "dest": "image/context.ts",
1537
+ "targets": [
1538
+ "react"
1539
+ ],
1540
+ "rewrite": {
1541
+ "@/core/context-menu": "./context-menu",
1542
+ "@/react/context-menu/styles": "./context-menu-styles"
1543
+ }
1544
+ },
1545
+ {
1546
+ "path": "src/react/context-menu/root.tsx",
1547
+ "dest": "image/root.tsx",
1548
+ "targets": [
1549
+ "react"
1550
+ ],
1551
+ "rewrite": {
1552
+ "@/core/context-menu": "./context-menu",
1553
+ "@/core/search": "./search-core",
1554
+ "@/core/keys": "./keys",
1555
+ "@/react/slot": "./slot",
1556
+ "@/react/context-menu/styles": "./context-menu-styles",
1557
+ "@/react/context-menu/context": "./context",
1558
+ "@/core/clipboard-menu": "./clipboard-menu"
1559
+ }
1560
+ },
1561
+ {
1562
+ "path": "src/react/context-menu/index.tsx",
1563
+ "dest": "image/context-menu-ui.tsx",
1564
+ "targets": [
1565
+ "react"
1566
+ ],
1567
+ "rewrite": {
1568
+ "@/react/context-menu/root": "./root",
1569
+ "@/react/context-menu/context": "./context",
1570
+ "@/react/context-menu/styles": "./context-menu-styles",
1571
+ "@/core/context-menu": "./context-menu",
1572
+ "@/core/keys": "./keys",
1573
+ "@/core/clipboard-menu": "./clipboard-menu"
1574
+ }
1575
+ },
1576
+ {
1577
+ "path": "src/react/image/menu.tsx",
1578
+ "dest": "image/menu.tsx",
1579
+ "targets": [
1580
+ "react"
1581
+ ],
1582
+ "rewrite": {
1583
+ "@/react/image/icons": "./icons",
1584
+ "@/react/image/types": "./types",
1585
+ "@/react/image/viewer": "./viewer",
1586
+ "@/core/image-viewer": "./image-viewer",
1587
+ "@/react/context-menu": "./context-menu-ui"
1588
+ }
1589
+ },
1590
+ {
1591
+ "path": "src/react/image/viewer.tsx",
1592
+ "dest": "image/viewer.tsx",
1593
+ "targets": [
1594
+ "react"
1595
+ ],
1596
+ "rewrite": {
1597
+ "@/react/image/icons": "./icons",
1598
+ "@/react/image/types": "./types",
1599
+ "@/react/image/styles": "./styles",
1600
+ "@/react/image/menu": "./menu",
1601
+ "@/core/image-viewer": "./image-viewer"
1602
+ }
1603
+ },
1604
+ {
1605
+ "path": "src/react/image/index.tsx",
1606
+ "dest": "image/index.tsx",
1607
+ "main": true,
1608
+ "targets": [
1609
+ "react"
1610
+ ],
1611
+ "rewrite": {
1612
+ "@/react/image/types": "./types",
1613
+ "@/react/image/viewer": "./viewer",
1614
+ "@/react/image/styles": "./styles"
1615
+ }
1616
+ },
1617
+ {
1618
+ "path": "recipes/image/styles.css",
1619
+ "dest": "image/styles.css",
1620
+ "targets": [
1621
+ "react"
1622
+ ],
1623
+ "style": "css"
1624
+ }
1625
+ ],
1626
+ "styles": true,
1627
+ "themeHooks": [
1628
+ "[data-enigma-image]",
1629
+ "[data-enigma-image][data-clickable]",
1630
+ "[data-enigma-image-trigger]",
1631
+ "[data-enigma-image-viewer]",
1632
+ "[data-enigma-image-bar]",
1633
+ "[data-enigma-image-counter]",
1634
+ "[data-enigma-image-button]",
1635
+ "[data-enigma-image-frame]",
1636
+ "[data-enigma-image-frame][data-zoomed]",
1637
+ "[data-enigma-image-frame][data-panning]",
1638
+ "[data-enigma-image-frame][data-loading]",
1639
+ "[data-enigma-image-nav]",
1640
+ "[data-enigma-image-spinner]",
1641
+ "[data-enigma-image-foot]",
1642
+ "[data-enigma-image-caption]",
1643
+ "[data-enigma-image-strip]",
1644
+ "[data-enigma-image-thumb]",
1645
+ "[data-enigma-image-viewer][data-state]",
1646
+ "[data-enigma-image-frame][data-flying]"
1647
+ ],
1648
+ "docs": "docs/notes/primitives.md#image",
1649
+ "source": "src/core/image-viewer.ts",
1650
+ "recipes": [
1651
+ "css"
1652
+ ]
1653
+ },
1654
+ {
1655
+ "name": "video",
1656
+ "title": "Video player",
1657
+ "description": "A video with the controls a video is expected to have, shaped after Plyr: a big play button over the poster, a scrubber showing what is buffered, current time and duration, volume that folds away until reached, subtitles with a language picker, a speed menu, picture in picture, casting to a TV and fullscreen. A right-click opens a menu the way YouTube's does - play, loop, speed, subtitles, copy the link or the link at this second - built from the context-menu primitive rather than hand-rolled. The keyboard is the platform's - space and K play, J and L jump ten seconds, the arrows nudge and set the volume, M mutes, F is fullscreen, C captions, a digit seeks to that tenth - and it stands down inside anything that takes text. The bar fades while playing and comes back on the first pointer move. The element stays the source of truth: playback, the subtitle list and the cast target are all read back from it rather than kept twice.",
1658
+ "targets": [
1659
+ "react"
1660
+ ],
1661
+ "entry": {
1662
+ "react": "@enigmax/primitives/react/video"
1663
+ },
1664
+ "exports": {
1665
+ "react": [
1666
+ "Video"
1667
+ ]
1668
+ },
1669
+ "files": [
1670
+ {
1671
+ "path": "src/core/context-menu.ts",
1672
+ "dest": "video/context-menu.ts",
1673
+ "targets": [
1674
+ "react"
1675
+ ],
1676
+ "rewrite": {
1677
+ "@/core/search": "./search-core",
1678
+ "@/core/keys": "./keys"
1679
+ }
1680
+ },
1681
+ {
1682
+ "path": "src/core/search.ts",
1683
+ "dest": "video/search-core.ts",
1684
+ "targets": [
1685
+ "react"
1686
+ ]
1687
+ },
1688
+ {
1689
+ "path": "src/core/keys.ts",
1690
+ "dest": "video/keys.ts",
1691
+ "targets": [
1692
+ "react"
1693
+ ]
1694
+ },
1695
+ {
1696
+ "path": "src/core/clipboard-menu.ts",
1697
+ "dest": "video/clipboard-menu.ts",
1698
+ "targets": [
1699
+ "react"
1700
+ ],
1701
+ "rewrite": {
1702
+ "@/core/context-menu": "./context-menu",
1703
+ "@/react/context-menu/styles": "./context-menu-styles"
1704
+ }
1705
+ },
1706
+ {
1707
+ "path": "src/react/slot.tsx",
1708
+ "dest": "video/slot.tsx",
1709
+ "targets": [
1710
+ "react"
1711
+ ],
1712
+ "rewrite": {
1713
+ "@/react/context-menu/styles": "./context-menu-styles"
1714
+ }
1715
+ },
1716
+ {
1717
+ "path": "src/react/context-menu/styles.ts",
1718
+ "dest": "video/context-menu-styles.ts",
1719
+ "targets": [
1720
+ "react"
1721
+ ],
1722
+ "rewrite": {
1723
+ "@/react/context-menu/styles": "./context-menu-styles"
1724
+ }
1725
+ },
1726
+ {
1727
+ "path": "recipes/context-menu/styles.css",
1728
+ "dest": "video/context-menu-styles.css",
1729
+ "targets": [
1730
+ "react"
1731
+ ],
1732
+ "style": "css",
1733
+ "rewrite": {
1734
+ "@/react/context-menu/styles": "./context-menu-styles"
1735
+ }
1736
+ },
1737
+ {
1738
+ "path": "src/react/context-menu/context.ts",
1739
+ "dest": "video/context.ts",
1740
+ "targets": [
1741
+ "react"
1742
+ ],
1743
+ "rewrite": {
1744
+ "@/core/context-menu": "./context-menu",
1745
+ "@/react/context-menu/styles": "./context-menu-styles"
1746
+ }
1747
+ },
1748
+ {
1749
+ "path": "src/react/context-menu/root.tsx",
1750
+ "dest": "video/root.tsx",
1751
+ "targets": [
1752
+ "react"
1753
+ ],
1754
+ "rewrite": {
1755
+ "@/core/context-menu": "./context-menu",
1756
+ "@/core/search": "./search-core",
1757
+ "@/core/keys": "./keys",
1758
+ "@/react/slot": "./slot",
1759
+ "@/react/context-menu/styles": "./context-menu-styles",
1760
+ "@/react/context-menu/context": "./context",
1761
+ "@/core/clipboard-menu": "./clipboard-menu"
1762
+ }
1763
+ },
1764
+ {
1765
+ "path": "src/react/context-menu/index.tsx",
1766
+ "dest": "video/context-menu-ui.tsx",
1767
+ "targets": [
1768
+ "react"
1769
+ ],
1770
+ "rewrite": {
1771
+ "@/react/context-menu/root": "./root",
1772
+ "@/react/context-menu/context": "./context",
1773
+ "@/react/context-menu/styles": "./context-menu-styles",
1774
+ "@/core/context-menu": "./context-menu",
1775
+ "@/core/keys": "./keys",
1776
+ "@/core/clipboard-menu": "./clipboard-menu"
1777
+ }
1778
+ },
1779
+ {
1780
+ "path": "src/core/player.ts",
1781
+ "dest": "video/player.ts",
1782
+ "targets": [
1783
+ "react"
1784
+ ]
1785
+ },
1786
+ {
1787
+ "path": "src/react/video/types.ts",
1788
+ "dest": "video/types.ts",
1789
+ "targets": [
1790
+ "react"
1791
+ ],
1792
+ "rewrite": {
1793
+ "@/react/context-menu/context": "./context"
1794
+ }
1795
+ },
1796
+ {
1797
+ "path": "src/react/video/icons.tsx",
1798
+ "dest": "video/icons.tsx",
1799
+ "targets": [
1800
+ "react"
1801
+ ]
1802
+ },
1803
+ {
1804
+ "path": "src/react/video/styles.ts",
1805
+ "dest": "video/styles.ts",
1806
+ "targets": [
1807
+ "react"
1808
+ ]
1809
+ },
1810
+ {
1811
+ "path": "src/react/video/rail.tsx",
1812
+ "dest": "video/rail.tsx",
1813
+ "targets": [
1814
+ "react"
1815
+ ],
1816
+ "rewrite": {
1817
+ "@/core/player": "./player"
1818
+ }
1819
+ },
1820
+ {
1821
+ "path": "src/react/video/menu.tsx",
1822
+ "dest": "video/menu.tsx",
1823
+ "targets": [
1824
+ "react"
1825
+ ],
1826
+ "rewrite": {
1827
+ "@/core/context-menu": "./context-menu",
1828
+ "@/react/context-menu": "./context-menu-ui"
1829
+ }
1830
+ },
1831
+ {
1832
+ "path": "src/react/video/index.tsx",
1833
+ "dest": "video/index.tsx",
1834
+ "main": true,
1835
+ "targets": [
1836
+ "react"
1837
+ ],
1838
+ "rewrite": {
1839
+ "@/core/player": "./player",
1840
+ "@/react/video/icons": "./icons",
1841
+ "@/react/video/rail": "./rail",
1842
+ "@/react/video/styles": "./styles",
1843
+ "@/react/video/types": "./types",
1844
+ "@/react/context-menu/context": "./context",
1845
+ "@/react/video/menu": "./menu"
1846
+ }
1847
+ },
1848
+ {
1849
+ "path": "recipes/video/styles.css",
1850
+ "dest": "video/styles.css",
1851
+ "targets": [
1852
+ "react"
1853
+ ],
1854
+ "style": "css"
1855
+ }
1856
+ ],
1857
+ "styles": true,
1858
+ "themeHooks": [
1859
+ "[data-enigma-video]",
1860
+ "[data-enigma-video][data-playing]",
1861
+ "[data-enigma-video][data-hidden]",
1862
+ "[data-enigma-video][data-fullscreen]",
1863
+ "[data-enigma-video-big]",
1864
+ "[data-enigma-video-overlay]",
1865
+ "[data-enigma-video-spinner]",
1866
+ "[data-enigma-video-controls]",
1867
+ "[data-enigma-video-button]",
1868
+ "[data-enigma-video-time]",
1869
+ "[data-enigma-video-rail]",
1870
+ "[data-enigma-video-track]",
1871
+ "[data-enigma-video-buffer]",
1872
+ "[data-enigma-video-played]",
1873
+ "[data-enigma-video-knob]",
1874
+ "[data-enigma-video-volume]",
1875
+ "[data-enigma-video-menu]",
1876
+ "[data-enigma-video-panel]",
1877
+ "[data-enigma-video-option]",
1878
+ "[data-enigma-video-heading]",
1879
+ "[data-enigma-video][data-casting]"
1880
+ ],
1881
+ "docs": "docs/notes/primitives.md#video",
1882
+ "source": "src/core/player.ts",
1883
+ "recipes": [
1884
+ "css"
1885
+ ]
1405
1886
  }
1406
1887
  ]
1407
1888
  }
@@ -82,8 +82,18 @@ export function isAction(entry: ContextMenuEntry): entry is ContextMenuAction {
82
82
  /** The fields the filter reads when the caller does not say. */
83
83
  export const CONTEXT_MENU_SEARCH_KEYS = ["label", "description", "group", "keywords"];
84
84
 
85
- /** Filtering six rows is worth a field; filtering three is a bigger panel for nothing. */
86
- export const SEARCHABLE_FROM = 8;
85
+ /**
86
+ * How many rows a level needs before it grows a filter on its own.
87
+ *
88
+ * Raised from 8, which turned out to be a number you can still READ. A menu of eight is
89
+ * scanned in one look, so the field was a row of chrome, a focus stop and a taller panel in
90
+ * exchange for nothing - the video player's own menu, at nine rows, is what showed it. Twelve
91
+ * is about where a list stops being a shape and starts being a list.
92
+ *
93
+ * It is only the DEFAULT. A menu whose rows arrive from somewhere - a list of files, a
94
+ * directory, anything fetched - says `searchable` and does not wait to grow into it.
95
+ */
96
+ export const SEARCHABLE_FROM = 12;
87
97
 
88
98
  /** Where a menu was opened. Viewport coordinates, which is what a pointer event reports. */
89
99
  export interface ContextMenuPoint {
@@ -141,6 +151,12 @@ export interface ContextMenuOptions {
141
151
  /** A row was invoked. The menu has already closed unless the row keeps it open. */
142
152
  onSelect?: (item: ContextMenuAction, path: string[]) => void;
143
153
  onOpenChange?: (open: boolean) => void;
154
+ /**
155
+ * Whether the ROOT level draws a filter. `"auto"` (the default) grows one from
156
+ * `SEARCHABLE_FROM` rows; `true` puts one there whatever the count, which is what a menu
157
+ * filling itself from somewhere wants; `false` never does.
158
+ */
159
+ searchable?: boolean | "auto";
144
160
  }
145
161
 
146
162
  export interface ContextMenuInstance {
@@ -235,7 +251,10 @@ export function createContextMenu(options: ContextMenuOptions = {}): ContextMenu
235
251
  }
236
252
 
237
253
  function searchableFor(item: ContextMenuAction | null, entries: readonly ContextMenuEntry[]): boolean {
238
- const asked = item?.searchable ?? "auto";
254
+ // The root has no item to carry the answer, so it reads the menu's own option - which
255
+ // is the only way a caller can turn the field on for rows they are about to fetch, or
256
+ // off for a menu they know is short.
257
+ const asked = (item ? item.searchable : opts.searchable) ?? "auto";
239
258
  if (asked !== "auto") return asked;
240
259
  return entries.filter(isAction).length >= SEARCHABLE_FROM;
241
260
  }