efficient-shell 5.6.1 → 7.7.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 (119) hide show
  1. package/README.md +270 -64
  2. package/THIRD_PARTY_NOTICES.md +212 -0
  3. package/dist/Browser-56LX7FTE.js +43 -0
  4. package/dist/Calculator-GBKLJHM6.js +29 -0
  5. package/dist/ConfirmDialog-PS5BXNAT.js +1 -0
  6. package/dist/CurrencyConverter-ZXY7XNG6.js +21 -0
  7. package/dist/Documents-SVKR757H.js +52 -0
  8. package/dist/Files-KSHU7ROB.js +87 -0
  9. package/dist/Notepad-5GT2GUCJ.js +25 -0
  10. package/dist/PdfViewer-YVAWFZVH.js +1 -0
  11. package/dist/PomodoroTimer-GAGDQ4NF.js +91 -0
  12. package/dist/Preview-YDCDW5NE.js +182 -0
  13. package/dist/Sidebar-IH6WUPKT.js +44 -0
  14. package/dist/Spreadsheet-SYR23K4I.js +37 -0
  15. package/dist/Stock-LH5CR667.js +16 -0
  16. package/dist/{Weather-RWI6NKB2.js → Weather-MZGIPR2R.js} +35 -35
  17. package/dist/WorldClock-DLB2RRLI.js +32 -0
  18. package/dist/apps/index.js +1 -1
  19. package/dist/bin/ui-check.js +1 -1
  20. package/dist/brand.css +1 -1
  21. package/dist/chunk-2ALIPI3D.js +1 -0
  22. package/dist/{chunk-JXAAZGLJ.js → chunk-2R5RTN5T.js} +1 -1
  23. package/dist/chunk-43XFZY4K.js +5 -0
  24. package/dist/chunk-4JGNJYVL.js +10 -0
  25. package/dist/{chunk-7WC3EOFS.js → chunk-5TOLXFQ6.js} +1 -1
  26. package/dist/chunk-6SCHK75C.js +108 -0
  27. package/dist/chunk-7IQ3B77H.js +1 -0
  28. package/dist/{chunk-TFETN2GI.js → chunk-B4PGVDB6.js} +1 -1
  29. package/dist/chunk-BUGGBB5J.js +1 -0
  30. package/dist/chunk-CJHT4VTF.js +91 -0
  31. package/dist/chunk-CLFUF3BH.js +9 -0
  32. package/dist/chunk-CQ2DLPPS.js +3 -0
  33. package/dist/{chunk-X4FJ54PP.js → chunk-FIEA5CGB.js} +1 -1
  34. package/dist/chunk-G4CTTSAR.js +11 -0
  35. package/dist/{chunk-YIH6JLMV.js → chunk-HIRMYFOF.js} +2 -2
  36. package/dist/chunk-JKHXDQEI.js +24 -0
  37. package/dist/{chunk-KXAUDC3A.js → chunk-JQRIAZDP.js} +35 -35
  38. package/dist/chunk-KNUR2UEG.js +1 -0
  39. package/dist/{chunk-WWF2EQXF.js → chunk-KONXUO5I.js} +1 -1
  40. package/dist/chunk-M4MCXII7.js +6 -0
  41. package/dist/{chunk-CLPJDJH4.js → chunk-M4TRVJTO.js} +1 -1
  42. package/dist/chunk-MSGBGLGI.js +29 -0
  43. package/dist/chunk-N7JTY3LU.js +21 -0
  44. package/dist/chunk-NODT4F2C.js +13 -0
  45. package/dist/chunk-OXTM3XZI.js +1 -0
  46. package/dist/chunk-PJPK2ADX.js +1 -0
  47. package/dist/chunk-PT4Z3KIA.js +12 -0
  48. package/dist/chunk-QRCDQPJA.js +1 -0
  49. package/dist/{chunk-SKB6L53D.js → chunk-QUVE5JZZ.js} +11 -11
  50. package/dist/{chunk-N3A3GWJI.js → chunk-R2TPTM4O.js} +12 -12
  51. package/dist/{chunk-GG7AE6OC.js → chunk-RBKIYZ7H.js} +1 -1
  52. package/dist/chunk-RUHUTZN4.js +1 -0
  53. package/dist/chunk-TCYS67ND.js +1016 -0
  54. package/dist/{chunk-AFYQTVZO.js → chunk-UVBK6YSR.js} +1 -1
  55. package/dist/client-DLm3Fvbc.d.ts +65 -0
  56. package/dist/file-intake/index.js +1 -1
  57. package/dist/i18n/index.d.ts +1 -1
  58. package/dist/icons/efficient-looks.d.ts +1 -1
  59. package/dist/icons/efficient-looks.js +4 -4
  60. package/dist/icons/efficient.d.ts +3 -3
  61. package/dist/icons/efficient.js +3 -3
  62. package/dist/icons/index.d.ts +12 -12
  63. package/dist/icons/index.js +1 -1
  64. package/dist/{index-ZI6vl2Wq.d.ts → index-BkBsXpfV.d.ts} +468 -161
  65. package/dist/index.d.ts +6 -4
  66. package/dist/index.js +635 -639
  67. package/dist/locales/zh-Hans.d.ts +1 -1
  68. package/dist/locales/zh-Hans.js +1 -1
  69. package/dist/map/index.js +22 -22
  70. package/dist/markdown/index.js +6 -6
  71. package/dist/markup/index.d.ts +460 -36
  72. package/dist/markup/index.js +1 -1
  73. package/dist/page-tabs/index.js +5 -5
  74. package/dist/pdf/index.js +1 -1
  75. package/dist/{registry-J-TU7zKx.d.ts → registry-Dw6QO2Ch.d.ts} +12 -9
  76. package/dist/{strings-BVB64Nck.d.ts → strings-BQtq9300.d.ts} +22 -2
  77. package/dist/telemetry/index.d.ts +39 -0
  78. package/dist/telemetry/index.js +1 -0
  79. package/dist/ui/index.d.ts +4 -3
  80. package/dist/ui/index.js +1 -1
  81. package/dist/ui.css +110 -75
  82. package/package.json +7 -21
  83. package/dist/Browser-RXGEZ77D.js +0 -43
  84. package/dist/Calculator-MVPKTZZF.js +0 -29
  85. package/dist/ConfirmDialog-XOYCYFA7.js +0 -1
  86. package/dist/CurrencyConverter-2IGOOR3I.js +0 -21
  87. package/dist/Documents-YBLR7WVX.js +0 -52
  88. package/dist/Files-7XNR5IL2.js +0 -87
  89. package/dist/Notepad-ZQYQXV75.js +0 -25
  90. package/dist/PdfViewer-SQVMMA7B.js +0 -1
  91. package/dist/PomodoroTimer-XIUN4M73.js +0 -91
  92. package/dist/Preview-YCOA5JPP.js +0 -182
  93. package/dist/Sidebar-VI7E3EKI.js +0 -44
  94. package/dist/Spreadsheet-SRAUU3OA.js +0 -37
  95. package/dist/Stock-7EKOAQ7C.js +0 -16
  96. package/dist/WorldClock-CEHWDFEO.js +0 -32
  97. package/dist/chunk-3HJTOINK.js +0 -1
  98. package/dist/chunk-4SWPNARR.js +0 -5
  99. package/dist/chunk-5ABLFFC5.js +0 -24
  100. package/dist/chunk-6LTDJKIL.js +0 -138
  101. package/dist/chunk-F6B3J3GW.js +0 -6
  102. package/dist/chunk-HZZNJHRH.js +0 -1
  103. package/dist/chunk-IMMHJIV5.js +0 -29
  104. package/dist/chunk-OGXU7QFW.js +0 -12
  105. package/dist/chunk-P4CIOJHP.js +0 -3
  106. package/dist/chunk-RBDGN4YU.js +0 -9
  107. package/dist/chunk-RC2EG6P4.js +0 -1026
  108. package/dist/chunk-RL626E7Q.js +0 -13
  109. package/dist/chunk-RMJZOKHY.js +0 -10
  110. package/dist/chunk-SFCDHHQP.js +0 -1
  111. package/dist/chunk-TNBCUZVE.js +0 -1
  112. package/dist/chunk-VWBQ2P5G.js +0 -108
  113. package/dist/chunk-XWSWYMGM.js +0 -2
  114. package/dist/chunk-YGC7AX3X.js +0 -11
  115. package/dist/chunk-Z7D6Y5WA.js +0 -21
  116. package/dist/icons/heroicons.d.ts +0 -6
  117. package/dist/icons/heroicons.js +0 -1
  118. package/dist/icons/lucide.d.ts +0 -6
  119. package/dist/icons/lucide.js +0 -1
package/dist/ui.css CHANGED
@@ -257,6 +257,12 @@
257
257
  --control-height-sm: 1.5rem;
258
258
  --control-height-md: 2rem;
259
259
  --control-height-lg: 2.5rem;
260
+
261
+ /* Row heights (Lewis, 2026-10-13): menu, list and sidebar rows, and the
262
+ main window bar. An exception to the control ladder; controls stay on
263
+ it. */
264
+ --row-height-menu: 2.25rem;
265
+ --row-height-window-bar: 2.75rem;
260
266
  }
261
267
 
262
268
  /* The default `utils/glass.ts` already assumes at `getMenuOpacity()`'s
@@ -775,7 +781,8 @@ html.rosh-reduce-transparency *::after {
775
781
  * so a selector rewrite of the dark theme touches one short block.
776
782
  */
777
783
  :root {
778
- /* glassStyle() — every menu, popup, listbox and tooltip in the kit. The
784
+ /* glassStyle() — every menu, popup and listbox in the kit; a Tooltip
785
+ bubble is always the solid one (solidSurfaceStyle()). The
779
786
  surface a popup is tinted from (frosted) or painted in (solid), and the
780
787
  stop across the middle of its gradient. Both chain to the ramp, so a host
781
788
  that restyles `--surface` moves its popups with it; one that wants its
@@ -815,22 +822,6 @@ html.rosh-reduce-transparency *::after {
815
822
  /* SidebarLayout's resize handle under the pointer, when no custom accent is
816
823
  set — the custom accent's `--accent-500` still wins, read where it is set. */
817
824
  --rosh-resize-handle: #3b82f6;
818
-
819
- /* DonutChart's default segment colours, in assignment order, and its track.
820
- NOT the `--viz-series-*` palette above: the donut predates it and its
821
- callers have been showing these hues, so this is the same eight in the
822
- same order. A host that wants one palette across every chart points these
823
- at the series tokens. The track is a translucent slate, read over either
824
- theme, which is why nothing here has a dark step. */
825
- --rosh-donut-1: #3b82f6;
826
- --rosh-donut-2: #22c55e;
827
- --rosh-donut-3: #f59e0b;
828
- --rosh-donut-4: #ef4444;
829
- --rosh-donut-5: #6366f1;
830
- --rosh-donut-6: #14b8a6;
831
- --rosh-donut-7: #a855f7;
832
- --rosh-donut-8: #64748b;
833
- --rosh-donut-track: rgba(148, 163, 184, 0.25);
834
825
  }
835
826
 
836
827
  /* ── Kit colours, dark ──────────────────────────────────────────────────────
@@ -901,10 +892,10 @@ html.rosh-reduce-transparency *::after {
901
892
  * IN NO LAYER, as they were in the portal, so they outrank a utility in the
902
893
  * same class attribute. That is as far as it goes. The dark and accent remaps
903
894
  * of a utility are `!important` and outrank these in turn, so a chip that is
904
- * to follow the theme wears `kbd-submit` and NO palette utility of its own: a
905
- * bare `<kbd>`, as the kit's two are, rather than `Kbd`, which brings gray
906
- * ones. `tests/browser/submitAffordance.check.mjs` reads the computed colours
907
- * under every theme.
895
+ * to follow the theme wears `kbd-submit` and NO palette utility of its own:
896
+ * `<Kbd tone="accent">`, or a bare `<kbd>` — never the default `Kbd`, which
897
+ * brings gray ones. `tests/browser/submitAffordance.check.mjs` reads the
898
+ * computed colours under every theme.
908
899
  */
909
900
  :root {
910
901
  --submit-bg: #2563eb;
@@ -930,30 +921,55 @@ html.rosh-reduce-transparency *::after {
930
921
  background-color: var(--submit-kbd-bg);
931
922
  }
932
923
 
924
+ /*
925
+ * ── Layers ───────────────────────────────────────────────────────────────────
926
+ *
927
+ * The stack order of every shell layer, in hundreds (owner ruling,
928
+ * 2026-10-12), as custom properties for markup: `z-(--z-taskbar)`. The same
929
+ * numbers are `Z_LAYERS` in `src/shell/zLayers.ts`, for inline styles, which
930
+ * explains each layer; `tests/zLayersHundreds.test.ts` keeps the two equal and
931
+ * holds the kit to naming a layer instead of writing its number.
932
+ */
933
+ :root {
934
+ --z-raised: 10;
935
+ --z-sticky: 20;
936
+ --z-in-box: 30;
937
+ --z-snap-preview: 900;
938
+ --z-window: 1000;
939
+ --z-peek: 1999;
940
+ --z-pinned-window: 2000;
941
+ --z-desktop-widget: 2100;
942
+ --z-taskbar: 2200;
943
+ --z-sidebar: 2300;
944
+ --z-taskbar-preview: 2350;
945
+ --z-start-menu: 2400;
946
+ --z-restore-tab: 2500;
947
+ --z-expose: 2600;
948
+ --z-overlay: 2700;
949
+ --z-toast: 2800;
950
+ --z-popup: 2900;
951
+ --z-menu: 2900;
952
+ --z-hint: 3000;
953
+ }
954
+
933
955
  /* ── Tooltip arrow ──────────────────────────────────────────────────────────
934
956
  * `Tooltip`'s pointer: a 10px square turned 45°, standing out of the bubble's
935
957
  * edge that faces the trigger. `data-side` is the side the BUBBLE is on, so
936
958
  * `top` means the bubble is above its trigger and the arrow points down.
937
959
  *
938
- * It is the bubble's own surface. `Tooltip` fills it inline with `glassFill()`
939
- * — the glass as one flat colour: exactly the bubble's opaque surface under
940
- * `rosh-reduce-transparency`, the surface at the glass's own alpha when
941
- * frosted (why not the gradient or a blur of its own: `glassFill` in
942
- * utils/glass.ts) — and gives it the bubble's border as `--rosh-tooltip-edge`.
943
- * So it is solid or frosted with the bubble, light or dark with it, and follows
944
- * whatever a theme or a host does to `--rosh-glass-*` and `--surface`: no
945
- * colour is written here.
960
+ * It is the bubble's own surface. `Tooltip` fills it inline with the bubble's
961
+ * solid fill (`solidSurfaceStyle()` in utils/glass.ts: opaque in both themes,
962
+ * Lewis 2026-10-13) and gives it the bubble's border as `--rosh-tooltip-edge`.
963
+ * So it is light or dark with the bubble, and follows whatever a theme or a
964
+ * host does to `--rosh-glass-*` and `--surface`: no colour is written here.
946
965
  *
947
966
  * Where it meets the bubble, two decisions:
948
- * * It is CLIPPED to its outward half. A frosted bubble is translucent, and
949
- * the inner half of a whole square laid over it would show through as a
950
- * darker diamond inside the bubble.
967
+ * * It is CLIPPED to its outward half, so nothing of it lies inside the
968
+ * bubble.
951
969
  * * Its centre — the clip line — sits on the INNER line of the bubble's 1px
952
970
  * border, so the outward half covers that border where the two meet, and
953
971
  * the border runs round bubble and arrow together: drawn on the arrow's two
954
- * outward edges only. On a solid bubble the join is invisible; on a frosted
955
- * one the hairline under the base shows through faintly, as anything
956
- * behind translucent glass does.
972
+ * outward edges only. On the solid bubble the join is invisible.
957
973
  *
958
974
  * Placed: `Tooltip` writes `left`/`top` as the point on the bubble's outer edge
959
975
  * the arrow is centred on, and each side's margins move the square's centre
@@ -1504,11 +1520,11 @@ html.rosh-reduce-transparency *::after {
1504
1520
  }
1505
1521
  .rosh-tl-ico { flex: none; width: 15px; height: 15px; align-self: center; margin-right: -3px; }
1506
1522
  .rosh-tl-ico svg { width: 15px; height: 15px; }
1507
- .rosh-tl-title { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: -0.005em; }
1523
+ .rosh-tl-title { margin: 0; font-size: var(--text-sm); font-weight: 600; letter-spacing: -0.005em; }
1508
1524
  /* `min-width: 0` is what lets a long meta line WRAP rather than push the
1509
1525
  actions onto a row of their own: a flex item's default minimum is its
1510
1526
  content, and five facts about a production order are wider than a card. */
1511
- .rosh-tl-meta { margin: 0; font-size: 12px; font-variant-numeric: tabular-nums; min-width: 0; }
1527
+ .rosh-tl-meta { margin: 0; font-size: var(--text-xs); font-variant-numeric: tabular-nums; min-width: 0; }
1512
1528
  .rosh-tl-meta b { font-weight: 500; }
1513
1529
  .rosh-tl-head-actions {
1514
1530
  display: inline-flex; align-items: center; gap: 10px; margin-left: auto; flex: none;
@@ -1519,7 +1535,7 @@ html.rosh-reduce-transparency *::after {
1519
1535
  .rosh-tl-play {
1520
1536
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 12px 0 10px;
1521
1537
  border-radius: 14px; cursor: pointer; white-space: nowrap;
1522
- font: inherit; font-size: 11.5px; font-weight: 500;
1538
+ font: inherit; font-size: var(--text-xs); font-weight: 500;
1523
1539
  background: var(--surface-raised); border-width: 1px; border-style: solid;
1524
1540
  transition: color 160ms ease-out, border-color 160ms ease-out;
1525
1541
  }
@@ -1530,12 +1546,12 @@ html.rosh-reduce-transparency *::after {
1530
1546
  margin-top: 14px; padding-top: 12px;
1531
1547
  border-top-width: 1px; border-top-style: solid;
1532
1548
  }
1533
- .rosh-tl-status { margin: 0; font-size: 12px; font-variant-numeric: tabular-nums; }
1549
+ .rosh-tl-status { margin: 0; font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
1534
1550
  .rosh-tl-legend { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
1535
1551
  .rosh-tl-legend > span {
1536
1552
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px 0 7px;
1537
1553
  border-width: 1px; border-style: solid; border-radius: 11px;
1538
- font-size: 10.5px; background: var(--surface-raised);
1554
+ font-size: var(--text-2xs); background: var(--surface-raised);
1539
1555
  }
1540
1556
  /* The legend's glyphs are the track's glyphs at legend size, so a chip can
1541
1557
  never describe a shape the rail no longer draws. */
@@ -1560,7 +1576,7 @@ html.rosh-reduce-transparency *::after {
1560
1576
  .rosh-tl-edge {
1561
1577
  position: absolute; white-space: nowrap;
1562
1578
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1563
- font-size: 10px; line-height: 1.3; color: var(--ink-muted);
1579
+ font-size: var(--text-2xs); line-height: 1.3; color: var(--ink-muted);
1564
1580
  }
1565
1581
  .rosh-tl-edge.is-end { transform: translateX(-100%); }
1566
1582
 
@@ -1597,7 +1613,7 @@ html.rosh-reduce-transparency *::after {
1597
1613
  .rosh-tl-tick.is-week { opacity: 0.5; }
1598
1614
  .rosh-tl-month, .rosh-tl-rulercut span {
1599
1615
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1600
- font-size: 10px; line-height: 1.1; color: var(--ink-faint);
1616
+ font-size: var(--text-2xs); line-height: 1.1; color: var(--ink-faint);
1601
1617
  }
1602
1618
  .rosh-tl-month { position: absolute; white-space: nowrap; }
1603
1619
  .rosh-tl-rulercut {
@@ -1614,7 +1630,7 @@ html.rosh-reduce-transparency *::after {
1614
1630
  }
1615
1631
  .rosh-tl-todaytag {
1616
1632
  position: absolute; white-space: nowrap; border-radius: 5px; padding: 1px 6px;
1617
- font-size: 10px; font-weight: 500; letter-spacing: 0.02em;
1633
+ font-size: var(--text-2xs); font-weight: 500; letter-spacing: 0.02em;
1618
1634
  color: var(--ink-muted); background: var(--surface-raised);
1619
1635
  }
1620
1636
 
@@ -1673,7 +1689,7 @@ html.rosh-reduce-transparency *::after {
1673
1689
  text over the rail is a mark's caption, and the undated things are a dashed
1674
1690
  cap at the end of a dashed tail. */
1675
1691
  .rosh-tl-flank {
1676
- flex: none; white-space: nowrap; font-size: 11px; font-weight: 500; line-height: 1;
1692
+ flex: none; white-space: nowrap; font-size: var(--text-2xs); font-weight: 500; line-height: 1;
1677
1693
  color: var(--ink-muted);
1678
1694
  }
1679
1695
  /* The caption over a mark — `v3` over a revision. Mono, like every other
@@ -1681,7 +1697,7 @@ html.rosh-reduce-transparency *::after {
1681
1697
  .rosh-tl-caption {
1682
1698
  position: absolute; transform: translateX(-50%); white-space: nowrap; pointer-events: none;
1683
1699
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1684
- font-size: 10px; line-height: 1.1; color: var(--ink-muted);
1700
+ font-size: var(--text-2xs); line-height: 1.1; color: var(--ink-muted);
1685
1701
  }
1686
1702
  /* The tail: from the end of the axis to the cap. Dashed, because it is not
1687
1703
  time — it is the distance to a date nobody has. */
@@ -1724,7 +1740,7 @@ html.rosh-reduce-transparency *::after {
1724
1740
  .rosh-tl-count {
1725
1741
  position: absolute; transform: translate(9px, -14px);
1726
1742
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1727
- font-size: 9px; font-weight: 600; line-height: 1; letter-spacing: -0.02em;
1743
+ font-size: var(--text-3xs); font-weight: 600; line-height: 1; letter-spacing: -0.02em;
1728
1744
  color: var(--tl-accent); pointer-events: none;
1729
1745
  padding: 1px 2px; border-radius: 4px; background: var(--surface-sunken);
1730
1746
  }
@@ -1736,7 +1752,7 @@ html.rosh-reduce-transparency *::after {
1736
1752
  }
1737
1753
  .rosh-tl-foldnum {
1738
1754
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1739
- font-size: 9px; font-weight: 600; line-height: 1; letter-spacing: -0.02em;
1755
+ font-size: var(--text-3xs); font-weight: 600; line-height: 1; letter-spacing: -0.02em;
1740
1756
  }
1741
1757
  .rosh-tl-node.is-active { box-shadow: 0 0 0 2px var(--surface-sunken), 0 0 0 5px var(--line); }
1742
1758
  /* The flash as the scrubber's thumb crosses a mark. It rides the same 160ms
@@ -1765,12 +1781,12 @@ html.rosh-reduce-transparency *::after {
1765
1781
  background: var(--surface-raised); border: 1px solid var(--line);
1766
1782
  }
1767
1783
  .rosh-tl-name {
1768
- font-size: 11px; font-weight: 500; line-height: 1.25; color: var(--ink-strong);
1784
+ font-size: var(--text-2xs); font-weight: 500; line-height: 1.25; color: var(--ink-strong);
1769
1785
  transition: color 160ms cubic-bezier(0, 0, 0.2, 1);
1770
1786
  }
1771
1787
  .rosh-tl-date, .rosh-tl-detail {
1772
1788
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1773
- font-size: 10px; line-height: 1.3; color: var(--ink-faint);
1789
+ font-size: var(--text-2xs); line-height: 1.3; color: var(--ink-faint);
1774
1790
  }
1775
1791
  .rosh-tl-detail { font-family: inherit; color: var(--ink-muted); margin-top: 2px; }
1776
1792
  .rosh-tl-label.is-current .rosh-tl-name { font-weight: 600; }
@@ -1789,7 +1805,7 @@ html.rosh-reduce-transparency *::after {
1789
1805
  }
1790
1806
  .rosh-tl-phase-label {
1791
1807
  position: absolute; transform: translateX(-50%); white-space: nowrap;
1792
- font-size: 9px; line-height: 1.2; pointer-events: none;
1808
+ font-size: var(--text-3xs); line-height: 1.2; pointer-events: none;
1793
1809
  }
1794
1810
 
1795
1811
  .rosh-tl-lead, .rosh-tl-cspan {
@@ -1800,7 +1816,7 @@ html.rosh-reduce-transparency *::after {
1800
1816
  .rosh-tl-pill {
1801
1817
  position: absolute; display: inline-flex; align-items: center; gap: 4px;
1802
1818
  height: 19px; padding: 0 7px; border-radius: 10px; cursor: pointer; white-space: nowrap;
1803
- font: inherit; font-size: 10px; font-weight: 500;
1819
+ font: inherit; font-size: var(--text-2xs); font-weight: 500;
1804
1820
  color: var(--ink); background: var(--surface); border: 1px solid currentColor;
1805
1821
  transition: box-shadow 160ms cubic-bezier(0, 0, 0.2, 1);
1806
1822
  }
@@ -1827,30 +1843,30 @@ html.rosh-reduce-transparency *::after {
1827
1843
  .rosh-tl-bubble.is-preview { max-width: 280px; min-width: 180px; }
1828
1844
  .rosh-tl-preview {
1829
1845
  display: flex; flex-direction: column; gap: 3px;
1830
- margin-top: 5px; font-size: 11px; color: var(--ink-muted);
1846
+ margin-top: 5px; font-size: var(--text-2xs); color: var(--ink-muted);
1831
1847
  }
1832
1848
  /* The way out of the popover and into the thing it is previewing. */
1833
1849
  .rosh-tl-bubble-open {
1834
1850
  margin-top: 6px; padding: 5px 0 0; width: 100%; text-align: left; cursor: pointer;
1835
1851
  background: none; border: 0; border-top-width: 1px; border-top-style: solid;
1836
1852
  border-top-color: var(--line);
1837
- font: inherit; font-size: 11px; font-weight: 500;
1853
+ font: inherit; font-size: var(--text-2xs); font-weight: 500;
1838
1854
  }
1839
1855
  .rosh-tl-bubble-open:hover { text-decoration: underline; }
1840
1856
  .rosh-tl-bubble-open:focus-visible:not(.rosh-host-focus *) { outline: 2px solid var(--tl-focus); outline-offset: 2px; }
1841
1857
 
1842
1858
  .rosh-tl-popover-head {
1843
- margin: 0 0 5px; font-size: 10px; font-weight: 500; letter-spacing: 0.06em;
1859
+ margin: 0 0 5px; font-size: var(--text-3xs); font-weight: 500; letter-spacing: 0.06em;
1844
1860
  text-transform: uppercase; color: var(--ink-faint);
1845
1861
  }
1846
1862
  .rosh-tl-popover ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
1847
- .rosh-tl-popover li { display: flex; gap: 8px; justify-content: space-between; font-size: 11px; }
1863
+ .rosh-tl-popover li { display: flex; gap: 8px; justify-content: space-between; font-size: var(--text-2xs); }
1848
1864
  /* What a FOLD says, which is the same list plus each member's own card: a run
1849
1865
  that is all one date can never be opened, so this is the only place those
1850
1866
  members exist. A column, because a preview under a row is a paragraph and not
1851
1867
  a third column. */
1852
1868
  .rosh-tl-fold-list ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
1853
- .rosh-tl-fold-list li { display: flex; flex-direction: column; font-size: 11px; }
1869
+ .rosh-tl-fold-list li { display: flex; flex-direction: column; font-size: var(--text-2xs); }
1854
1870
  .rosh-tl-foldrow { display: flex; gap: 8px; justify-content: space-between; margin: 0; }
1855
1871
  .rosh-tl-fold-list .rosh-tl-preview { margin-top: 2px; }
1856
1872
 
@@ -1889,7 +1905,7 @@ html.rosh-reduce-transparency *::after {
1889
1905
  reads as the link it is. */
1890
1906
  .rosh-tl-open {
1891
1907
  padding: 0; border: 0; background: none; cursor: pointer; text-align: left;
1892
- font: inherit; font-size: 11px; font-weight: 500; line-height: 1.25;
1908
+ font: inherit; font-size: var(--text-2xs); font-weight: 500; line-height: 1.25;
1893
1909
  }
1894
1910
  .rosh-tl-open:hover { text-decoration: underline; }
1895
1911
  /* The radius shapes whichever outline is drawn, the host's included, so it is
@@ -1902,7 +1918,7 @@ html.rosh-reduce-transparency *::after {
1902
1918
  position: absolute; transform: translateX(-50%); z-index: 5; white-space: nowrap;
1903
1919
  transition: left 120ms cubic-bezier(0.22, 1, 0.36, 1);
1904
1920
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
1905
- font-size: 10.5px; font-weight: 500; padding: 3px 8px; border-radius: 7px;
1921
+ font-size: var(--text-2xs); font-weight: 500; padding: 3px 8px; border-radius: 7px;
1906
1922
  background: var(--ink-strongest); color: var(--surface);
1907
1923
  }
1908
1924
  .rosh-tl-chip::after {
@@ -1911,12 +1927,12 @@ html.rosh-reduce-transparency *::after {
1911
1927
  }
1912
1928
 
1913
1929
  .rosh-tl-pending { padding-top: 16px; }
1914
- .rosh-tl-pending-head { margin: 0 0 8px; font-size: 10px; font-weight: 500; color: var(--ink-faint); }
1930
+ .rosh-tl-pending-head { margin: 0 0 8px; font-size: var(--text-2xs); font-weight: 500; color: var(--ink-faint); }
1915
1931
  .rosh-tl-ghosts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
1916
- .rosh-tl-ghosts li { display: flex; align-items: center; gap: 9px; font-size: 11px; color: var(--ink-muted); }
1932
+ .rosh-tl-ghosts li { display: flex; align-items: center; gap: 9px; font-size: var(--text-2xs); color: var(--ink-muted); }
1917
1933
  .rosh-tl-ghosts .rosh-tl-node { position: relative; --rosh-tl-shift: translate(0, 0); flex: none; }
1918
1934
  .rosh-tl-ghosts b { font-weight: 500; color: var(--ink-faint); }
1919
- .rosh-tl-more { margin-top: 9px; font-size: 11px; text-decoration: underline; cursor: pointer; }
1935
+ .rosh-tl-more { margin-top: 9px; font-size: var(--text-2xs); text-decoration: underline; cursor: pointer; }
1920
1936
 
1921
1937
  /* The vertical variant: under a 320px track the axis is abandoned rather than
1922
1938
  squeezed, and the connector carries the fill. */
@@ -1940,7 +1956,7 @@ html.rosh-reduce-transparency *::after {
1940
1956
  .rosh-tl-v > li[aria-current] .rosh-tl-name { font-weight: 600; }
1941
1957
  .rosh-tl-vgap {
1942
1958
  position: relative; margin: 0; padding: 0 0 14px 26px; min-height: 20px;
1943
- font-family: var(--font-mono); font-size: 10px; color: var(--ink-faint);
1959
+ font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-faint);
1944
1960
  }
1945
1961
 
1946
1962
  /* ── Timeline motion ────────────────────────────────────────────────────────
@@ -2041,13 +2057,17 @@ html.rosh-reduce-transparency *::after {
2041
2057
  :is([data-theme="dark"], .dark) .bg-gray-50 { background-color: var(--surface-sunken) !important; }
2042
2058
  :is([data-theme="dark"], .dark) .bg-gray-100 { background-color: var(--surface) !important; }
2043
2059
  :is([data-theme="dark"], .dark) .bg-gray-200 { background-color: var(--surface-raised) !important; }
2044
- /* Segmented's chosen option. The track is bg-gray-100 and the chosen option
2045
- bg-white, and the two remaps above send BOTH to --surface: in dark the chosen
2046
- option was the colour of its own track, told apart only by a faint shadow and
2047
- ink a step brighter than the others'. Raised instead, as the light theme's
2048
- white pill is raised off its grey track. After the remaps on purpose: the
2049
- same weight, so the later rule wins. */
2050
- :is([data-theme="dark"], .dark) .rosh-segmented-on { background-color: var(--surface-raised) !important; }
2060
+ /* Segmented's chosen option has no rule here. It was a white chip, which the
2061
+ remaps above sent to the same --surface as its bg-gray-100 track, so a rule
2062
+ raised it. Since 2026-10-12 (owner) it is the solid blue chip pill Tabs
2063
+ draw, and blue-600 is not remapped: the same chip in both themes, 3.1:1 on
2064
+ the dark track (tests/choiceStrip.test.tsx). */
2065
+ /* The choice strip's track (Segmented, pill Tabs) keeps the --surface fill
2066
+ above in dark, so the chip stays 3:1 on it, and gets its frame from a 1px
2067
+ INSET ring in --line-strong instead: a lighter fill would drop the chip to
2068
+ 2.4:1. Inset, so no size changes. Dark only; light has no edge (owner,
2069
+ 2026-10-13: the strip floated with no frame in dark). */
2070
+ :is([data-theme="dark"], .dark) .rosh-choice-track { box-shadow: inset 0 0 0 1px var(--line-strong) !important; }
2051
2071
 
2052
2072
  /* Text */
2053
2073
  :is([data-theme="dark"], .dark) .text-gray-900 { color: var(--ink-strongest) !important; }
@@ -2210,8 +2230,12 @@ html.rosh-reduce-transparency *::after {
2210
2230
 
2211
2231
  Inputs — apply the form-input dark styling, but skip elements that
2212
2232
  explicitly opt into a transparent background (e.g. the start-menu
2213
- search) so they keep their parent's frosted-glass tile. */
2214
- :is([data-theme="dark"], .dark) input:not(.bg-transparent):not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):where(:root:not(.rosh-host-elements) *),
2233
+ search) so they keep their parent's frosted-glass tile, and a filter that
2234
+ is on (`.rosh-field-on`, forms/styles.ts), whose accent border and wash
2235
+ are painted by their own utilities' remaps. Both in ONE `:not()`: a
2236
+ selector list there counts as its most specific item, so adding the
2237
+ second changes this rule's specificity not at all. */
2238
+ :is([data-theme="dark"], .dark) input:not(.bg-transparent, .rosh-field-on):not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):where(:root:not(.rosh-host-elements) *),
2215
2239
  :is([data-theme="dark"], .dark) select:not(.bg-transparent):where(:root:not(.rosh-host-elements) *),
2216
2240
  :is([data-theme="dark"], .dark) textarea:not(.bg-transparent):where(:root:not(.rosh-host-elements) *) {
2217
2241
  background-color: var(--surface-sunken) !important;
@@ -2234,6 +2258,17 @@ html.rosh-reduce-transparency *::after {
2234
2258
  }
2235
2259
  }
2236
2260
 
2261
+ /* ── A field that shows its choice in the placeholder's place ───────────────
2262
+ An open `SearchableSelect` — several values, or a `filter` — is its own
2263
+ search box, so its value is the typed text, empty until the person types.
2264
+ Until then it shows what is chosen where the placeholder goes
2265
+ (`.rosh-field-shows-choice`), in the field's own ink rather than the hint
2266
+ grey: it is the value, not a hint ("All Procedures" would say the filter is
2267
+ off). `inherit` takes the field's colour in every theme — the ink utility's
2268
+ remap, or the bare dark input rule's. `input.` so it outranks the
2269
+ `placeholder:` utility whatever the stylesheet order. */
2270
+ input.rosh-field-shows-choice::placeholder { color: inherit; opacity: 1; }
2271
+
2237
2272
  /* Status badges — tone down brightness in dark mode (matches StatusBadge.tsx semantic groups) */
2238
2273
  :is([data-theme="dark"], .dark) .bg-gray-100.text-gray-800 { background-color: var(--surface-raised) !important; color: var(--ink) !important; }
2239
2274
  :is([data-theme="dark"], .dark) .bg-gray-300.text-gray-800 { background-color: var(--line-strong) !important; color: var(--ink-strongest) !important; }
@@ -2518,7 +2553,7 @@ html.rosh-reduce-transparency *::after {
2518
2553
  transition: opacity 300ms ease, transform 300ms ease;
2519
2554
  align-items: center;
2520
2555
  gap: 8px;
2521
- font-size: 13px;
2556
+ font-size: var(--text-sm);
2522
2557
  font-weight: 500;
2523
2558
  color: var(--rosh-toast-ink);
2524
2559
  max-width: min(90vw, 460px);
@@ -2553,7 +2588,7 @@ html.rosh-reduce-transparency *::after {
2553
2588
  }
2554
2589
  .rosh-notif-body { flex: 1; min-width: 0; }
2555
2590
  .rosh-notif-title {
2556
- font-size: 11px;
2591
+ font-size: var(--text-2xs);
2557
2592
  font-weight: 600;
2558
2593
  color: var(--rosh-toast-info);
2559
2594
  text-transform: uppercase;
@@ -2561,7 +2596,7 @@ html.rosh-reduce-transparency *::after {
2561
2596
  margin-bottom: 2px;
2562
2597
  }
2563
2598
  .rosh-notif-msg {
2564
- font-size: 13px;
2599
+ font-size: var(--text-sm);
2565
2600
  font-weight: 500;
2566
2601
  color: var(--rosh-toast-ink);
2567
2602
  line-height: 1.4;
@@ -2570,7 +2605,7 @@ html.rosh-reduce-transparency *::after {
2570
2605
  flex-shrink: 0;
2571
2606
  padding: 4px;
2572
2607
  color: var(--rosh-toast-dismiss);
2573
- font-size: 18px;
2608
+ font-size: var(--text-lg);
2574
2609
  line-height: 1;
2575
2610
  transition: color 0.2s;
2576
2611
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efficient-shell",
3
- "version": "5.6.1",
3
+ "version": "7.7.0",
4
4
  "description": "Desktop-style React UI shell — windows, taskbar, start menu, sticky notes, frosted glass theming, and bundled apps.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Efficient Pty Ltd",
@@ -83,16 +83,6 @@
83
83
  "import": "./dist/icons/index.js",
84
84
  "default": "./dist/icons/index.js"
85
85
  },
86
- "./icons/heroicons": {
87
- "types": "./dist/icons/heroicons.d.ts",
88
- "import": "./dist/icons/heroicons.js",
89
- "default": "./dist/icons/heroicons.js"
90
- },
91
- "./icons/lucide": {
92
- "types": "./dist/icons/lucide.d.ts",
93
- "import": "./dist/icons/lucide.js",
94
- "default": "./dist/icons/lucide.js"
95
- },
96
86
  "./icons/efficient": {
97
87
  "types": "./dist/icons/efficient.d.ts",
98
88
  "import": "./dist/icons/efficient.js",
@@ -103,6 +93,11 @@
103
93
  "import": "./dist/icons/efficient-looks.js",
104
94
  "default": "./dist/icons/efficient-looks.js"
105
95
  },
96
+ "./telemetry": {
97
+ "types": "./dist/telemetry/index.d.ts",
98
+ "import": "./dist/telemetry/index.js",
99
+ "default": "./dist/telemetry/index.js"
100
+ },
106
101
  "./styles.css": "./dist/styles.css",
107
102
  "./ui.css": "./dist/ui.css",
108
103
  "./themes.css": "./dist/themes.css",
@@ -117,12 +112,10 @@
117
112
  ],
118
113
  "peerDependencies": {
119
114
  "@headlessui/react": ">=2",
120
- "@heroicons/react": ">=2",
121
115
  "@tanstack/react-query": ">=5",
122
116
  "axios": ">=1.6",
123
117
  "dxf-viewer": "*",
124
118
  "i18next": ">=26",
125
- "lucide-react": ">=0.577",
126
119
  "mammoth": "*",
127
120
  "maplibre-gl": ">=6",
128
121
  "online-3d-viewer": "*",
@@ -141,7 +134,6 @@
141
134
  },
142
135
  "devDependencies": {
143
136
  "@headlessui/react": "^2.2.10",
144
- "@heroicons/react": "^2.2.0",
145
137
  "@tailwindcss/cli": "^4.2.4",
146
138
  "@tanstack/react-query": "^5.100.5",
147
139
  "@types/jsdom": "^28.0.3",
@@ -153,7 +145,6 @@
153
145
  "esbuild": "^0.27.0",
154
146
  "i18next": "^26.4.3",
155
147
  "jsdom": "^26.1.0",
156
- "lucide-react": "^1.55.0",
157
148
  "mammoth": "^1.8.0",
158
149
  "maplibre-gl": "6.11.2",
159
150
  "online-3d-viewer": "^0.18.0",
@@ -171,6 +162,7 @@
171
162
  "terser": "^5.51.2",
172
163
  "tsup": "^8.0.0",
173
164
  "typescript": "^5.3.0",
165
+ "web-vitals": "6.2.3",
174
166
  "xlsx": "^0.18.5"
175
167
  },
176
168
  "scripts": {
@@ -200,9 +192,6 @@
200
192
  "@headlessui/react": {
201
193
  "optional": true
202
194
  },
203
- "@heroicons/react": {
204
- "optional": true
205
- },
206
195
  "@tanstack/react-query": {
207
196
  "optional": true
208
197
  },
@@ -215,9 +204,6 @@
215
204
  "i18next": {
216
205
  "optional": true
217
206
  },
218
- "lucide-react": {
219
- "optional": true
220
- },
221
207
  "mammoth": {
222
208
  "optional": true
223
209
  },
@@ -1,43 +0,0 @@
1
- import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-RBDGN4YU.js";import"./chunk-SFCDHHQP.js";import{WindowTitle as r}from"./chunk-VWBQ2P5G.js";import"./chunk-YGC7AX3X.js";import"./chunk-DSSLOQDW.js";import"./chunk-5A7MWTXX.js";import"./chunk-OGXU7QFW.js";import"./chunk-P4CIOJHP.js";import{confirm as a}from"./chunk-IMMHJIV5.js";import"./chunk-RMJZOKHY.js";import"./chunk-AFYQTVZO.js";import"./chunk-HZZNJHRH.js";import"./chunk-X4FJ54PP.js";import"./chunk-D65T4H6J.js";import{ChevronLeftFallback as n,ChevronRightFallback as l,RefreshFallback as s,HomeFallback as i,StarFallback as c,ExternalFallback as m,HelpFallback as d,NoSymbolFallback as u}from"./chunk-6LTDJKIL.js";import{Icon as h}from"./chunk-XWSWYMGM.js";import"./chunk-TNBCUZVE.js";import"./chunk-C3QOHMR6.js";import{useRef as p,useEffect as b,useState as g}from"react";import{jsxs as f,jsx as k,Fragment as x}from"react/jsx-runtime";var w="react-os-shell:browser-bookmarks",y="react-os-shell:browser-homepage",v="https://en.wikipedia.org/wiki/Main_Page",N=[{label:"Wikipedia",url:"https://en.wikipedia.org/wiki/Main_Page"},{label:"DevDocs",url:"https://devdocs.io"},{label:"Example",url:"https://example.com"}],j=new Set(["ac ad ae af ag ai al am ao aq ar as at au aw ax az ba bb bd be bf bg bh bi","bj bm bn bo br bs bt bw by bz ca cc cd cf cg ch ci ck cl cm cn co cr cu cv","cw cx cy cz de dj dk dm do dz ec ee eg er es et eu fi fj fk fm fo fr ga gd","ge gf gg gh gi gl gm gn gp gq gr gs gt gu gw gy hk hm hn hr ht hu id ie il","im in io iq ir is it je jm jo jp ke kg kh ki km kn kp kr kw ky kz la lb lc","li lk lr ls lt lu lv ly ma mc md me mg mh mk ml mm mn mo mp mq mr ms mt mu","mv mw mx my mz na nc ne nf ng ni nl no np nr nu nz om pa pe pf pg ph pk pl","pm pn pr ps pt pw py qa re ro rs ru rw sa sb sc sd se sg sh si sk sl sm sn","so sr ss st su sv sx sy sz tc td tf tg th tj tk tl tm tn to tr tt tv tw tz","ua ug uk us uy uz va vc ve vg vi vn vu wf ws ye yt za zm zw","com net org edu gov mil int info biz name pro app dev xyz online site tech","store shop cloud design digital agency studio media news blog live life","world today email systems solutions services software page link space host","press wiki team group works careers finance capital energy academy"].join(" ").split(" "));function C(e){let t=e.trim();return t?/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?t:function(e){const t=/^([\w-]+\.)+([a-z]{2,})(\/.*)?$/i.exec(e);return null!==t&&j.has(t[2].toLowerCase())}(t)?"https://"+t:"https://duckduckgo.com/?q="+encodeURIComponent(t):""}var z=["duckduckgo.com","developer.mozilla.org","google.com","gmail.com","youtube.com","facebook.com","instagram.com","whatsapp.com","twitter.com","x.com","github.com","gitlab.com","linkedin.com","reddit.com","pinterest.com","amazon.com","amazon.ca","amazon.co.uk","apple.com","icloud.com","microsoft.com","outlook.com","live.com","office.com","netflix.com","spotify.com","paypal.com","stripe.com","chat.openai.com","chatgpt.com","claude.ai"];function W(){if("undefined"==typeof window)return N;try{const e=localStorage.getItem(w);if(!e)return N;const t=JSON.parse(e);if(Array.isArray(t)&&t.every(e=>"string"==typeof e?.url))return t}catch{}return N}function S(){return"undefined"==typeof window?v:localStorage.getItem(y)||v}function H(){const u=p(void 0);void 0===u.current&&(u.current=e()),b(()=>{null!=u.current&&t(u.current)},[]);const x=u.current?C(u.current.url):"",[v,N]=g(S),[j,z]=g(x||v),[H,D]=g(j),[O,E]=g([j]),[M,P]=g(0),[T,I]=g(0),[J,U]=g(W),[X,F]=g(!1),[G,Q]=g(null),q=p(null),A=p(null);b(()=>{try{localStorage.setItem(w,JSON.stringify(J))}catch{}},[J]);const B=e=>{const t=C(e);t&&(z(t),D(t),E(e=>{const o=e.slice(0,M+1);return o.push(t),o}),P(e=>e+1),F(!1))},Y=()=>{"undefined"!=typeof window&&window.open(j,"_blank","noopener,noreferrer")},K=()=>{const e=G?.trim();e?(U(t=>[...t,{label:e,url:j}]),Q(null)):Q(null)};b(()=>{if(null===G)return;q.current?.focus(),q.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||Q(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==G]);const Z=e=>{U(t=>t.filter((t,o)=>o!==e))},$=M>0,V=M<O.length-1,_=J.some(e=>e.url===j),ee="p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";/* @__PURE__ */
2
- return f("div",{className:"relative flex flex-col h-full bg-white",children:[
3
- /* @__PURE__ */k(r,{title:`Browser - ${R(j)}`}),
4
- /* @__PURE__ */k(o,{app:"browser"}),
5
- /* @__PURE__ */f("div",{className:"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0",children:[
6
- /* @__PURE__ */k("button",{onClick:()=>{if(M>0){const e=M-1;P(e),z(O[e]),D(O[e]),F(!1)}},disabled:!$,className:ee,title:"Back",children:/* @__PURE__ */k(h,{name:"chevron-left",fallback:n,className:"h-4 w-4",strokeWidth:2})}),
7
- /* @__PURE__ */k("button",{onClick:()=>{if(M<O.length-1){const e=M+1;P(e),z(O[e]),D(O[e]),F(!1)}},disabled:!V,className:ee,title:"Forward",children:/* @__PURE__ */k(h,{name:"chevron-right",fallback:l,className:"h-4 w-4",strokeWidth:2})}),
8
- /* @__PURE__ */k("button",{onClick:()=>I(e=>e+1),className:ee,title:"Refresh",children:/* @__PURE__ */k(h,{name:"refresh",fallback:s,className:"h-4 w-4",strokeWidth:1.8})}),
9
- /* @__PURE__ */k("button",{onClick:()=>B(v),className:ee,title:"Home",children:/* @__PURE__ */k(h,{name:"home",fallback:i,className:"h-4 w-4",strokeWidth:1.8})}),
10
- /* @__PURE__ */k("form",{onSubmit:e=>{e.preventDefault(),B(H)},className:"flex-1 flex items-center mx-1",children:/* @__PURE__ */f("div",{className:"flex items-center w-full bg-white border border-gray-300 rounded focus-within:border-blue-400 focus-within:ring-1 focus-within:ring-blue-200",children:[
11
- /* @__PURE__ */k("span",{className:"px-2 text-gray-400 text-xs",children:j.startsWith("https://")?"🔒":"⚠️"}),
12
- /* @__PURE__ */k("input",{type:"text",value:H,onChange:e=>D(e.target.value),onFocus:e=>e.target.select(),className:"flex-1 px-1 py-1 text-sm bg-transparent outline-none font-mono",spellCheck:!1,placeholder:"Enter URL or search…"}),j!==H&&/* @__PURE__ */k("button",{type:"button",onClick:()=>D(j),className:"px-1.5 text-[10px] text-gray-400 hover:text-gray-700",title:"Reset to current URL",children:"×"})]})}),
13
- /* @__PURE__ */k("button",{"data-bookmark-popover":!0,onClick:()=>_?Z(J.findIndex(e=>e.url===j)):void Q(R(j)),className:ee+" "+(_?"text-yellow-500":""),title:_?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */k(h,{name:"star",fallback:c,className:"h-4 w-4",fill:_?"currentColor":"none",strokeWidth:1.5})}),
14
- /* @__PURE__ */k("button",{onClick:Y,className:ee,title:"Open in new tab",children:/* @__PURE__ */k(h,{name:"external",fallback:m,className:"h-4 w-4",strokeWidth:1.5})}),
15
- /* @__PURE__ */k("button",{onClick:()=>F(e=>!e),className:ee,title:"Embedding help",children:/* @__PURE__ */k(h,{name:"help",fallback:d,className:"h-4 w-4",strokeWidth:1.5})})]}),null!==G&&/* @__PURE__ */f("div",{"data-bookmark-popover":!0,className:"absolute right-3 top-12 z-30 w-72 bg-white border border-gray-200 rounded-md shadow-lg p-3",children:[
16
- /* @__PURE__ */k("div",{className:"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1",children:"Bookmark this page"}),
17
- /* @__PURE__ */k("div",{className:"text-[11px] text-gray-400 truncate mb-2 font-mono",title:j,children:j}),
18
- /* @__PURE__ */k("input",{ref:q,type:"text",value:G,onChange:e=>Q(e.target.value),onKeyDown:e=>{"Enter"===e.key?K():"Escape"===e.key&&Q(null)},placeholder:"Name",className:"w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-200"}),
19
- /* @__PURE__ */f("div",{className:"flex justify-end gap-1 mt-2",children:[
20
- /* @__PURE__ */k("button",{onClick:()=>Q(null),className:"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded",children:"Cancel"}),
21
- /* @__PURE__ */k("button",{onClick:K,disabled:!G.trim(),className:"px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-40",children:"Save"})]})]}),
22
- /* @__PURE__ */f("div",{className:"flex items-center gap-0.5 px-2 py-1 border-b border-gray-200 bg-white shrink-0 overflow-x-auto",children:[0===J.length&&/* @__PURE__ */k("span",{className:"text-[11px] text-gray-400 italic px-2",children:"No bookmarks yet — star the address bar to add one."}),J.map((e,t)=>/* @__PURE__ */f("button",{onClick:()=>B(e.url),onContextMenu:async o=>{o.preventDefault();await a({title:"Remove bookmark",message:`"${e.label}" will be removed from your bookmarks.`,confirmLabel:"Remove",variant:"danger"})&&Z(t)},className:"flex items-center gap-1.5 px-2 py-0.5 rounded text-[12px] text-gray-700 hover:bg-gray-100 whitespace-nowrap",title:`${e.url}\n(right-click to remove)`,children:[
23
- /* @__PURE__ */k("img",{src:`https://icons.duckduckgo.com/ip3/${new URL(e.url).hostname}.ico`,alt:"",className:"h-3.5 w-3.5",onError:e=>{e.target.style.visibility="hidden"}}),e.label]},t)),
24
- /* @__PURE__ */k("div",{className:"flex-1"}),
25
- /* @__PURE__ */k("button",{onClick:()=>{N(j);try{localStorage.setItem(y,j)}catch{}},className:"px-2 py-0.5 text-[11px] text-gray-500 hover:text-gray-800",title:"Set current page as homepage",children:"Set as home"})]}),
26
- /* @__PURE__ */k("div",{className:"flex-1 relative min-h-0 bg-gray-50",children:/* @__PURE__ */k(L,{url:j,iframeKey:T,iframeRef:A,openExternal:Y,showHelp:X,dismissHelp:()=>F(!1)})})]})}function R(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return e}}function L({url:e,iframeKey:t,iframeRef:o,openExternal:r,showHelp:a,dismissHelp:n}){const[l,s]=g(!1);b(()=>{s(!1)},[e]);return function(e){try{const t=new URL(e).hostname.toLowerCase();return z.some(e=>t===e||t.endsWith("."+e))}catch{return!1}}(e)&&!l?/* @__PURE__ */k("div",{className:"absolute inset-0 flex items-center justify-center bg-white p-8",children:/* @__PURE__ */f("div",{className:"max-w-md text-center",children:[
27
- /* @__PURE__ */k(h,{name:"no-symbol",fallback:u,className:"h-14 w-14 mx-auto text-gray-300 mb-3",strokeWidth:1.2}),
28
- /* @__PURE__ */f("h3",{className:"text-base font-semibold text-gray-800 mb-1",children:[R(e)," can't be embedded"]}),
29
- /* @__PURE__ */f("p",{className:"text-sm text-gray-500 mb-4",children:["This site sends an ",
30
- /* @__PURE__ */k("span",{className:"font-mono text-xs",children:"X-Frame-Options"})," ","or ",
31
- /* @__PURE__ */k("span",{className:"font-mono text-xs",children:"Content-Security-Policy"})," header that refuses iframe embedding. The browser blocks the load before our app can do anything about it."]}),
32
- /* @__PURE__ */f("div",{className:"flex flex-col items-center gap-2",children:[
33
- /* @__PURE__ */f("button",{onClick:r,className:"px-4 py-2 bg-blue-500 text-white text-sm rounded hover:bg-blue-600 inline-flex items-center gap-2",children:[
34
- /* @__PURE__ */k(h,{name:"external",fallback:m,className:"h-4 w-4",strokeWidth:1.5}),"Open in a new tab"]}),
35
- /* @__PURE__ */k("button",{onClick:()=>s(!0),className:"text-xs text-gray-500 hover:text-gray-800 underline",children:"Try loading it here anyway"})]})]})}):/* @__PURE__ */f(x,{children:[
36
- /* @__PURE__ */k("iframe",{ref:o,src:e,className:"absolute inset-0 w-full h-full bg-white",sandbox:"allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals",referrerPolicy:"no-referrer-when-downgrade"},t+e),a&&/* @__PURE__ */f("div",{className:"absolute top-2 right-2 max-w-sm bg-white border border-gray-200 rounded-md shadow-lg p-3 text-xs text-gray-700 z-10",children:[
37
- /* @__PURE__ */k("div",{className:"font-medium text-gray-900 mb-1",children:"Why is this page blank?"}),
38
- /* @__PURE__ */f("p",{className:"mb-2",children:["Most major sites (Google, GitHub, banks, news) refuse to be embedded in an iframe via ",
39
- /* @__PURE__ */k("span",{className:"font-mono",children:"X-Frame-Options"})," or Content Security Policy. There's no workaround — the browser blocks the load before our app can do anything."]}),
40
- /* @__PURE__ */f("p",{children:["Hit the ",
41
- /* @__PURE__ */k("span",{className:"font-medium",children:"↗"})," button to open the page in a real new tab. Sites that ",
42
- /* @__PURE__ */k("em",{children:"do"})," allow embedding (Wikipedia, DevDocs, your own apps) work fine in here."]}),
43
- /* @__PURE__ */k("button",{onClick:n,className:"mt-2 text-[11px] text-blue-600 hover:underline",children:"Got it"})]})]})}export{H as default};
@@ -1,29 +0,0 @@
1
- import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-7WC3EOFS.js";import{useWidgetSettings as n}from"./chunk-VWBQ2P5G.js";import"./chunk-YGC7AX3X.js";import"./chunk-DSSLOQDW.js";import"./chunk-5A7MWTXX.js";import"./chunk-OGXU7QFW.js";import"./chunk-P4CIOJHP.js";import"./chunk-IMMHJIV5.js";import"./chunk-RMJZOKHY.js";import"./chunk-AFYQTVZO.js";import"./chunk-HZZNJHRH.js";import"./chunk-X4FJ54PP.js";import"./chunk-D65T4H6J.js";import{CheckFallbackB as l,CopyFallbackB as r}from"./chunk-6LTDJKIL.js";import{Icon as c}from"./chunk-XWSWYMGM.js";import"./chunk-TNBCUZVE.js";import"./chunk-C3QOHMR6.js";import{useState as a,useRef as i,useCallback as o,useEffect as s}from"react";import{jsxs as u,Fragment as d,jsx as h}from"react/jsx-runtime";var m="calc_appearance";function b(){const[b,k]=a("0"),[p,g]=a(null),[f,y]=a(null),[N,x]=a(!1),[v,C]=a(""),[$,j]=a([]),[w,E]=a(!1),[S,W]=a(()=>e(m)),[T,F]=a(!1),[O,H]=a(S),J=i(null);n(o(()=>{H({...S}),F(!0)},[S]));const M=o(e=>{C(""),k(t=>N||"0"===t?(x(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[N]),X=o(()=>{k("0"),g(null),y(null),x(!1)},[]),A=o((e,t,n)=>{switch(n){case"+":return e+t;case"-":return e-t;case"×":return e*t;case"÷":return 0===t?0:e/t;default:return t}},[]),D=o(e=>{const t=parseFloat(b);if(null!==p&&f&&!N){const e=A(p,t,f);k(String(e)),g(e),j(n=>[`${p} ${f} ${t} = ${e}`,...n].slice(0,20))}else g(t);y(e),x(!0)},[b,p,f,N,A]),I=o(()=>{if(null===p||!f)return;const e=parseFloat(b),t=A(p,e,f),n=`${p} ${f} ${e} =`;j(e=>[`${n} ${t}`,...e].slice(0,20)),C(n),k(String(t)),g(null),y(null),x(!0)},[b,p,f,A]),L=o(()=>{k(e=>String(parseFloat(e)/100))},[]),P=o(()=>{k(e=>e.startsWith("-")?e.slice(1):"0"===e?e:"-"+e)},[]);s(()=>{const e=e=>{const t=e.target.tagName;"INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t&&(e.key>="0"&&e.key<="9"?M(e.key):"."===e.key?M("."):"+"===e.key?D("+"):"-"===e.key?D("-"):"*"===e.key?D("×"):"/"===e.key?(e.preventDefault(),D("÷")):"Enter"===e.key||"="===e.key?("Enter"===e.key&&e.target instanceof Node&&J.current?.contains(e.target)&&e.preventDefault(),I()):"Escape"===e.key?X():"Backspace"===e.key?k(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&L())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[M,D,I,X,L]);const B="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",Q=`${B} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,Z=`${B} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,G=`${B} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,R=`${B} bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800`;/* @__PURE__ */
2
- return u(d,{children:[
3
- /* @__PURE__ */u("div",{ref:J,className:"flex flex-col h-full",style:{opacity:S.activeOpacity/100,backdropFilter:S.activeBlur>0?`blur(${S.activeBlur}px)`:void 0},children:[
4
- /* @__PURE__ */u("div",{className:"bg-slate-200 rounded-t-lg px-4 py-2 group/display relative flex flex-col justify-end min-h-[120px] border-b border-slate-300",children:[
5
- /* @__PURE__ */h("div",{className:"flex flex-col justify-end flex-1 overflow-hidden",children:$.slice(0,3).reverse().map((e,t)=>/* @__PURE__ */h("div",{className:"text-[11px] text-slate-400 text-right font-mono truncate",children:e},t))}),(v||f&&null!==p)&&/* @__PURE__ */h("div",{className:"text-base text-slate-600 text-right font-mono",children:v||`${p} ${f} ${N?"":b}`}),
6
- /* @__PURE__ */u("div",{className:"flex items-center gap-2",children:[
7
- /* @__PURE__ */h("button",{onClick:()=>{navigator.clipboard.writeText(b),E(!0),setTimeout(()=>E(!1),1200)},title:"Copy result",className:"shrink-0 text-slate-300 hover:text-slate-500 transition-colors opacity-0 group-hover/display:opacity-100",children:/* @__PURE__ */h(c,w?{name:"check",fallback:l,className:"h-5 w-5 text-green-500",strokeWidth:2}:{name:"copy",fallback:r,className:"h-5 w-5",strokeWidth:2})}),
8
- /* @__PURE__ */h("div",{className:"text-right text-4xl font-mono font-bold text-slate-800 truncate flex-1",children:(e=>{const t=parseFloat(e);return isNaN(t)||e.endsWith(".")||e.endsWith(".0")||Math.abs(t)<1e15&&e.length<16?e:t.toExponential(6)})(b)})]})]}),
9
- /* @__PURE__ */u("div",{className:"grid grid-cols-4 grid-rows-5 gap-1.5 flex-1 min-h-0 p-2",children:[
10
- /* @__PURE__ */h("button",{onClick:X,className:G,children:"AC"}),
11
- /* @__PURE__ */h("button",{onClick:P,className:G,children:"+/−"}),
12
- /* @__PURE__ */h("button",{onClick:L,className:G,children:"%"}),
13
- /* @__PURE__ */h("button",{onClick:()=>D("÷"),className:`${Z} ${"÷"===f?"ring-2 ring-blue-400":""}`,children:"÷"}),
14
- /* @__PURE__ */h("button",{onClick:()=>M("7"),className:Q,children:"7"}),
15
- /* @__PURE__ */h("button",{onClick:()=>M("8"),className:Q,children:"8"}),
16
- /* @__PURE__ */h("button",{onClick:()=>M("9"),className:Q,children:"9"}),
17
- /* @__PURE__ */h("button",{onClick:()=>D("×"),className:`${Z} ${"×"===f?"ring-2 ring-blue-400":""}`,children:"×"}),
18
- /* @__PURE__ */h("button",{onClick:()=>M("4"),className:Q,children:"4"}),
19
- /* @__PURE__ */h("button",{onClick:()=>M("5"),className:Q,children:"5"}),
20
- /* @__PURE__ */h("button",{onClick:()=>M("6"),className:Q,children:"6"}),
21
- /* @__PURE__ */h("button",{onClick:()=>D("-"),className:`${Z} ${"-"===f?"ring-2 ring-blue-400":""}`,children:"−"}),
22
- /* @__PURE__ */h("button",{onClick:()=>M("1"),className:Q,children:"1"}),
23
- /* @__PURE__ */h("button",{onClick:()=>M("2"),className:Q,children:"2"}),
24
- /* @__PURE__ */h("button",{onClick:()=>M("3"),className:Q,children:"3"}),
25
- /* @__PURE__ */h("button",{onClick:()=>D("+"),className:`${Z} ${"+"===f?"ring-2 ring-blue-400":""}`,children:"+"}),
26
- /* @__PURE__ */h("button",{onClick:()=>M("0"),className:`${Q} col-span-2`,children:"0"}),
27
- /* @__PURE__ */h("button",{onClick:()=>M("."),className:Q,children:"."}),
28
- /* @__PURE__ */h("button",{onClick:I,className:R,children:"="})]})]}),
29
- /* @__PURE__ */h(t,{open:T,onClose:()=>F(!1),title:"Calculator Settings",appearance:O,onAppearanceChange:H,onSave:()=>{W(O),localStorage.setItem(m,JSON.stringify(O)),F(!1)}})]})}export{b as default};
@@ -1 +0,0 @@
1
- export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-IMMHJIV5.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-6LTDJKIL.js";import"./chunk-XWSWYMGM.js";import"./chunk-TNBCUZVE.js";import"./chunk-C3QOHMR6.js";