efficient-shell 4.177.0 → 4.180.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 (66) hide show
  1. package/README.md +384 -7
  2. package/dist/{Browser-MFFTBGEB.js → Browser-RZFOKBSF.js} +14 -14
  3. package/dist/Calculator-R5OEHQ67.js +29 -0
  4. package/dist/ConfirmDialog-CMNQZQA3.js +1 -0
  5. package/dist/{CurrencyConverter-KZPE7ZCC.js → CurrencyConverter-AMXUOQR2.js} +7 -7
  6. package/dist/{Documents-ZD227WZC.js → Documents-VD32HWDQ.js} +7 -7
  7. package/dist/{Files-BLGT4RLF.js → Files-NAY3WK6O.js} +31 -31
  8. package/dist/{Notepad-LUK2IFHD.js → Notepad-AHRPMF57.js} +10 -10
  9. package/dist/PdfViewer-3SC3LE4U.js +1 -0
  10. package/dist/{PomodoroTimer-LHPV6QXG.js → PomodoroTimer-LE6J2KUU.js} +26 -26
  11. package/dist/Preview-OKR5QRQP.js +188 -0
  12. package/dist/{Sidebar-4GIZSTD5.js → Sidebar-BQ4P5LBI.js} +21 -21
  13. package/dist/Spreadsheet-RME4IQ43.js +37 -0
  14. package/dist/{Stock-XSDFN7U2.js → Stock-GWVG2INU.js} +4 -4
  15. package/dist/{Weather-7YDUDMCO.js → Weather-APBCG4TO.js} +14 -14
  16. package/dist/{WorldClock-Q2JHBKLS.js → WorldClock-2LMZYKWR.js} +7 -7
  17. package/dist/apps/index.d.ts +4 -2
  18. package/dist/apps/index.js +1 -1
  19. package/dist/bin/ui-check.js +1 -1
  20. package/dist/{chunk-L3U2R7DH.js → chunk-3DGTIWZP.js} +1 -1
  21. package/dist/{chunk-AZO5NPB4.js → chunk-4VTHXNGZ.js} +625 -625
  22. package/dist/{chunk-KS7OSQ3Y.js → chunk-5ZDM6WIC.js} +11 -11
  23. package/dist/{chunk-E2D54MVV.js → chunk-6CFBF543.js} +2 -2
  24. package/dist/{chunk-LCTSBQBJ.js → chunk-7WZEFHPS.js} +1 -1
  25. package/dist/chunk-BSJIBRWC.js +1 -0
  26. package/dist/chunk-C3QOHMR6.js +1 -0
  27. package/dist/{chunk-YJRC6IKD.js → chunk-CIXQKCFA.js} +4 -4
  28. package/dist/{chunk-Q7UGGJ5X.js → chunk-FORN7LG7.js} +1 -1
  29. package/dist/chunk-J3LIIIHJ.js +1 -0
  30. package/dist/{chunk-7H6Q5TNN.js → chunk-KDRAU4XQ.js} +8 -8
  31. package/dist/{chunk-ZOPYAOUP.js → chunk-KVOFUFPP.js} +1 -1
  32. package/dist/{chunk-KDHXRJIX.js → chunk-LK7V32MR.js} +1 -1
  33. package/dist/{chunk-TZ2BPFCT.js → chunk-N6STBYXR.js} +111 -111
  34. package/dist/{chunk-54OP3M3K.js → chunk-NHIGOEZF.js} +1 -1
  35. package/dist/{chunk-PE6MTNFO.js → chunk-PE4F4MJE.js} +4 -4
  36. package/dist/chunk-R7EBJKN2.js +69 -0
  37. package/dist/chunk-RQOP5JAJ.js +9 -0
  38. package/dist/{chunk-AI6HQ55O.js → chunk-SVO3ES2E.js} +1 -1
  39. package/dist/{chunk-RKR5V4QR.js → chunk-T4CFSGSL.js} +6 -6
  40. package/dist/{chunk-N6BJG6AL.js → chunk-UAIVAA5X.js} +11 -11
  41. package/dist/{chunk-REXHKIIJ.js → chunk-WNEO7TSP.js} +1 -1
  42. package/dist/{chunk-XJYXKO7K.js → chunk-ZAE6ROV7.js} +15 -15
  43. package/dist/file-intake/index.js +1 -1
  44. package/dist/i18n/index.d.ts +3 -2
  45. package/dist/i18n/index.js +1 -1
  46. package/dist/{index-BS_HzJCc.d.ts → index-HAwjA-hn.d.ts} +25 -4
  47. package/dist/index.d.ts +3 -3
  48. package/dist/index.js +656 -656
  49. package/dist/locales/zh-Hans.d.ts +59 -0
  50. package/dist/locales/zh-Hans.js +1 -0
  51. package/dist/map/index.js +3 -3
  52. package/dist/page-tabs/index.js +4 -4
  53. package/dist/pdf/index.js +1 -1
  54. package/dist/{strings-C3kt6WTH.d.ts → strings-ZbotP_I6.d.ts} +368 -0
  55. package/dist/ui/index.d.ts +2 -2
  56. package/dist/ui/index.js +1 -1
  57. package/package.json +6 -1
  58. package/dist/Calculator-AGQQYMMZ.js +0 -29
  59. package/dist/ConfirmDialog-6PVUVYXZ.js +0 -1
  60. package/dist/PdfViewer-RKRGO7Q2.js +0 -1
  61. package/dist/Preview-5CALO6PW.js +0 -187
  62. package/dist/Spreadsheet-F3VBCPHF.js +0 -37
  63. package/dist/chunk-3YTHR7IC.js +0 -1
  64. package/dist/chunk-4PCIZFDR.js +0 -9
  65. package/dist/chunk-MFXG5BWL.js +0 -1
  66. package/dist/chunk-VIIBZ6DE.js +0 -69
package/README.md CHANGED
@@ -862,7 +862,9 @@ Round 4:
862
862
  fade: no chevron, never opens, still focusable, `aria-readonly`. It draws the
863
863
  desktop field on touch too, since a native `<select>` can only fade.
864
864
  `renderValue(chosen)` draws the closed field, given the chosen options in
865
- the options' order. The label stays the words a screen reader reads.
865
+ the options' order. The label stays the words a screen reader reads, unless
866
+ `valueText(chosen)` gives others: for a drawing that says something else than
867
+ the label (a list that offers "No style" under a box that reads "Custom").
866
868
  - **`SearchableSelect`**: option groups (`{ label, options }`), `multiple`
867
869
  (`value: string[]`, `onChange(string[])`, toggles and stays open, each chosen
868
870
  option checked), `disabled` options (greyed, skipped by the arrows, inert to
@@ -951,7 +953,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
951
953
  | `DataTable` | Read-only table for server-driven lists: it renders and reports, and never sorts or pages its own `data`. Controlled sort and pager, row selection, column groups, pinned columns, windowed rendering. `onRow` gives a row `onClick`, a `className`, any `data-*` attributes for its `<tr>` — a test's or a stylesheet's hook (`data-testid`, `data-state`) — the pointer and the keyboard coming in and out (`onMouseEnter` … `onBlur`) and `current`. `rowHref` makes each row one real link (`onRowPress` a button) with its controls still pressable — see [DataTable rows that are links](#datatable-rows-that-are-links). `stackOnNarrow` turns each row into a labelled card on a narrow container — see [DataTable on a narrow screen](#datatable-on-a-narrow-screen). |
952
954
  | `Pagination` | Numbered page control (pairs with tables; complements `ListFooter`). |
953
955
  | `Sparkline`, `LineChart`, `BarChart`, `DonutChart`, `ScatterChart` | Dependency-free inline-SVG charts (`currentColor`-themed). `LineChart` is the multi-series trend with optional scale, legend, dots and area fill. `ScatterChart` takes `xDomain` / `yDomain` to override the derived axis, and `xScale` / `yScale` of `'log'` for a long tail; a point outside a supplied domain is dropped and counted in the accessible label. |
954
- | `BulkImportGrid` | Paste-or-upload bulk entry with column mapping, duplicate review and optional sum-merge. Hands resolved rows to `onImport`; owns no persistence. The whole panel takes a dropped CSV; the Upload CSV button opens the same dialog. |
956
+ | `BulkImportGrid` | Paste-or-upload bulk entry with column mapping, duplicate review and optional sum-merge. Hands resolved rows to `onImport`; owns no persistence. The whole panel takes a dropped CSV; the Upload CSV button opens the same dialog. Its words are the strings catalog's `bulkImport` section (a `description` prop wins), and its totals are written in the provider's `locale`. |
955
957
  | `UndoProvider`, `UndoControls` | One undo stack per form window, covering its fields, line items and bulk imports. Register state with `useUndoable` and the shell shows the Undo/Redo pair itself, leftmost in the window footer, as soon as the form has state and the window is editing (a draft, a duplicate, Edit mode) or the form has said `useUndoCanEdit(true)` — a view that merely holds state gets nothing — it joins a footer that is there for other reasons and never creates one, and the mobile chrome (footer hidden) gets nothing. A form mounts `UndoControls` by hand only for a place the footer is not (a plain overlay, a section header); a hand mount claims the stack and the shell then mounts nothing for it, so a form shows one pair wherever it chose to put it. Binds ⌘Z / ⇧⌘Z (and Ctrl+Y) except while the caret is in a field, where the browser's own undo wins. `WindowManager` already mounts one per window, scoped with `windowId` so a keypress reaches only the frontmost window; pass `windowId` yourself for any provider you mount outside a `<Modal>`, or two open windows will step back together. Offered to anyone who may edit the record — gate with `canEdit` and/or `perms`; a reader sees no controls and records no history. The shell-level provider cannot know the record's permissions, so a read-only form nests its own `<UndoProvider canEdit={false}>` to shadow it. A provider nested inside a window puts its own pair in the footer on the same footer terms — it joins a footer that is there for other reasons, never creates one or holds it open, and shows nothing on the mobile chrome — but its `canEdit` takes the place of the editing check: the form that nested it has already said whether the record may be edited, so pass `canEdit={isEditing}` (or the lock) rather than leaving the default. |
956
958
  | `Calendar` | Month grid with full keyboard navigation (arrows, Home/End, PageUp/Down) and `role="grid"` semantics. Single or range. Days of the months either side are quieter than the month's own but keep AA contrast: they are dates a person can press. The shared grid behind `DatePicker` and `DateRangePicker`. `weekStartsOn` defaults to the provider locale's first day of the week (`firstDayOfWeek`), Sunday without one. |
957
959
  | `DashboardTemplate`, `DataTablePage`, `FormLayoutPage`, `CheckoutTemplate`, `EmailTemplate`, `ChatTemplate`, `GalleryTemplate`, `AuthScreen`, `ErrorPage` | Zero-prop starter page templates composed from the primitives. |
@@ -1007,7 +1009,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
1007
1009
  | `utilityApps`, `documentApps`, `webApps` | Subsets of `bundledApps`. |
1008
1010
  | `Calculator`, `Spreadsheet`, `Weather`, `CurrencyConverter`, `PomodoroTimer`, `TodoList`, `Browser` | Lazy components — use directly in custom registry entries. |
1009
1011
  | `PdfViewer` | Lazy component — the PDF reader on its own, for embedding. See below. |
1010
- | `BUILTIN_APP_INFO` | Per-app metadata for the document/web apps (Spreadsheets, Notepad, Documents, Preview, Files, Browser): display name, independent app version and one-line description. Drives each app's "About" dialog (window title menu → About <App>), which also shows the shell version. |
1012
+ | `BUILTIN_APP_INFO` | Per-app metadata for the document/web apps (Spreadsheets, Notepad, Documents, Preview, Files, Browser): display name, independent app version and one-line description. Drives each app's "About" dialog (window title menu → About <App>), which also shows the shell version. The dialog's words, and each app's description, are the strings catalog's `aboutApp` section; `description` here is its English default. |
1011
1013
 
1012
1014
  #### An embedded PDF — `PdfViewer`
1013
1015
 
@@ -1695,6 +1697,43 @@ const { language, languages, setLanguage } = useShellLanguage();
1695
1697
  except after a language change, when the tab takes its route's title until
1696
1698
  its page mounts and titles it again.
1697
1699
 
1700
+ #### Shipped languages — `efficient-shell/locales/zh-Hans`
1701
+
1702
+ The shell ships its own catalogue for Simplified Chinese (mainland usage), so
1703
+ its window controls, pagers and dialogs read the same in every host:
1704
+
1705
+ ```tsx
1706
+ import { zhHansStrings } from 'efficient-shell/locales/zh-Hans';
1707
+
1708
+ <ShellLanguageProvider languages={LANGUAGES} language="zh-Hans" strings={zhHansStrings()}>
1709
+ <App />
1710
+ </ShellLanguageProvider>
1711
+
1712
+ // or, without the language provider:
1713
+ <ShellStringsProvider value={zhHansStrings()} locale="zh-Hans">…</ShellStringsProvider>
1714
+ ```
1715
+
1716
+ - **It is a draft.** No native speaker has reviewed it yet.
1717
+ `ZH_HANS_REVIEWED_SECTIONS` (same subpath) lists the catalogue sections one
1718
+ has signed off, and it is empty: the whole catalogue is draft. The shell only
1719
+ reports this; whether to offer the language meanwhile is the host's call.
1720
+ - **It is the whole catalogue.** `zhHansStrings(locale = 'zh-Hans')` returns a
1721
+ complete `ShellStrings`, the word-order entries included, so no key falls
1722
+ back to English. Its counts are written in `locale`. A key you want said
1723
+ differently is one spread away: `{ ...zh, dialog: { ...zh.dialog, ok: '好' } }`.
1724
+ - **A caller's words are spaced the Chinese way.** A label or a name you pass
1725
+ in is closed up against Chinese and set off by a space when it is Latin
1726
+ (`复制采购订单号`, `复制 SO-0041`), so a host part-way through its own
1727
+ translation reads correctly in both.
1728
+ - **What stays in Latin letters** is notation: file formats (`PDF`, `CSV`,
1729
+ `DXF`), key names (`Esc`, `Enter`), units, the drawing panel's commands and
1730
+ package names.
1731
+ - **Nothing loads it by accident.** The subpath is its own entry with no React
1732
+ and no peer, safe to call from server code, and neither `efficient-shell` nor
1733
+ `efficient-shell/ui` imports it: a host that offers one language downloads
1734
+ none of it. `createShellI18n` (below) fetches it with a dynamic import when
1735
+ `zh-Hans` is activated.
1736
+
1698
1737
  #### Your own copy — `efficient-shell/i18n`
1699
1738
 
1700
1739
  The catalog above is the shell's words. A host's own copy (its column
@@ -1712,7 +1751,7 @@ import orders from '../locales/en/orders.json';
1712
1751
  export const { i18n, t, activate } = createShellI18n({
1713
1752
  copy: { common, orders }, // English, bundled
1714
1753
  load: language => import(`../locales/${language}/index.ts`).then(m => m.default),
1715
- loadShellStrings: language => SHELL_CATALOGS[language]?.(), // the shell's own words
1754
+ // loadShellStrings: omitted, the shell loads the catalogue it ships for the language
1716
1755
  });
1717
1756
  ```
1718
1757
 
@@ -1731,6 +1770,12 @@ const { default: App } = await import('./App');
1731
1770
  together, then switches `t`. A key the language lacks falls back to the
1732
1771
  source language. If either load fails the page stays in the source language
1733
1772
  and the result says `failed: true`; it never rejects into a blank page.
1773
+ - **The shell's catalogue comes by default.** With no `loadShellStrings`,
1774
+ `activate` loads the catalogue the shell ships for the language
1775
+ (`efficient-shell/locales/zh-Hans`, lazily) and hands it back as
1776
+ `activation.strings`; a language the shell does not ship activates with
1777
+ `strings: undefined` and the shell's own words stay in English. Pass
1778
+ `loadShellStrings` to supply your own instead: it wins.
1734
1779
  - **Import the app after `activate`.** Module-level constants call `t` when
1735
1780
  they are imported and keep what it said, so copy read before `activate` stays
1736
1781
  in the source language for the life of the page. `activate` reports that on
@@ -1750,15 +1795,35 @@ and event names (`sounds`). Their own props — `submitLabel`, `doneLabel`, the
1750
1795
  PDF button's `label`, a list's `errorTitle` — still win, and the keys a sound
1751
1796
  scheme is stored under are identifiers, never translated.
1752
1797
 
1798
+ **The status and file surfaces are in the catalog too.**
1799
+ `ServerStatusIndicator`'s tooltip and card (`serverStatus`), `BulkImportGrid`
1800
+ with its column mapper and both duplicate reviews (`bulkImport`), the Preview
1801
+ window (`preview`) with its drawing panel and command bar (`drawing`) and its
1802
+ 3D panel (`model`), `ImageAnnotator` (`annotator`), what `openAttachment` says
1803
+ when a stored file cannot be shown in a window (`attachment`) and a bundled
1804
+ app's About dialog (`aboutApp`). The PDF panel was already `pdf`. A caller's own
1805
+ words still win: the bulk grid's `description`, a staged `convertingMessage`,
1806
+ `openAttachment`'s `loadingMessage`, a fetch error's own message. The times on
1807
+ the status card and the totals over the bulk grid are written in `locale`, and
1808
+ exactly as before without one.
1809
+
1753
1810
  **What is not in the catalog, on purpose:** month and weekday names (the
1754
1811
  `locale` supplies them); file-format names in `BrandAssetEditor`'s default
1755
1812
  `acceptHint` and the `20ft`/`40ft` container codes (notation, not language); the
1756
1813
  `Kbd` shortcut constants (key symbols); `STAGES` labels (data a consumer's own
1757
1814
  tables read); the sample content of the starter templates (`DashboardTemplate`,
1758
1815
  `AuthScreen` and the rest are demos to copy, not components to configure); and
1759
- console warnings, which are for developers.
1760
-
1761
- **The full catalog** — 56 sections, 525 keys. A function's default is shown
1816
+ console warnings, which are for developers. In the Preview window the same
1817
+ goes for file extensions and the two optional packages' names, the drawing
1818
+ panel's command names (`DI`, `DIM`, `H`, `V`, `Z`, `LA`: what is typed is the
1819
+ same in every language) and its `ΔX`/`ΔY`, the axis letters and `⊥` of the 3D
1820
+ panel, a measurement's unit (`18.56 mm`, `1.250 m`) and the status card's
1821
+ latency (`42 ms`), a colour swatch's hex code, and the names of the files a
1822
+ snapshot or an annotated image is saved under. A bundled app's NAME is its
1823
+ window-registry label and is not in the catalog either; its one-line
1824
+ description is.
1825
+
1826
+ **The full catalog** — 64 sections, 781 keys. A function's default is shown
1762
1827
  with sample arguments.
1763
1828
 
1764
1829
  <details><summary><code>window</code> — 17 keys</summary>
@@ -2678,6 +2743,318 @@ with sample arguments.
2678
2743
 
2679
2744
  </details>
2680
2745
 
2746
+ <details><summary><code>serverStatus</code> — 27 keys</summary>
2747
+
2748
+ | Key | Type | English default |
2749
+ |---|---|---|
2750
+ | `connected` | `string` | `Connected` |
2751
+ | `disconnected` | `string` | `Disconnected` |
2752
+ | `checking` | `string` | `Checking…` |
2753
+ | `lastOkTitle` | `(status: string, time: string) => string` | `{status} · last ok {time}` |
2754
+ | `details` | `string` | `Server connection details` |
2755
+ | `lastPoll` | `(ago: string) => string` | `Last poll {ago}.` |
2756
+ | `lastFailure` | `(ago: string) => string` | `Last failure {ago}.` |
2757
+ | `firstPoll` | `string` | `First poll in flight…` |
2758
+ | `server` | `string` | `Server` |
2759
+ | `protocol` | `string` | `Protocol` |
2760
+ | `browser` | `string` | `Browser` |
2761
+ | `online` | `string` | `Online` |
2762
+ | `offline` | `string` | `Offline` |
2763
+ | `lastOk` | `string` | `Last OK` |
2764
+ | `lastFail` | `string` | `Last fail` |
2765
+ | `latency` | `string` | `Latency` |
2766
+ | `poll` | `string` | `Poll` |
2767
+ | `pollEvery` | `(seconds: number) => string` | `every 3 s` |
2768
+ | `session` | `string` | `Session` |
2769
+ | `user` | `string` | `User` |
2770
+ | `notSignedIn` | `string` | `Not signed in` |
2771
+ | `role` | `string` | `Role` |
2772
+ | `build` | `string` | `Build` |
2773
+ | `app` | `string` | `App` |
2774
+ | `userAgent` | `string` | `UA` |
2775
+ | `pingHint` | `string` | `Click ↻ to ping now` |
2776
+ | `refresh` | `string` | `Refresh` |
2777
+
2778
+ </details>
2779
+
2780
+ <details><summary><code>bulkImport</code> — 29 keys</summary>
2781
+
2782
+ | Key | Type | English default |
2783
+ |---|---|---|
2784
+ | `description` | `string` | `Paste from spreadsheets, type directly, or upload a CSV. Rows don't need to be in order — they'll be matched. Values not in the list will be added to the end. Fields left blank will not be affected.` |
2785
+ | `lines` | `(count: number) => string` | `3 lines` |
2786
+ | `total` | `(label: string, value: string) => string` | `{label}: {value}` |
2787
+ | `clear` | `string` | `Clear` |
2788
+ | `upload` | `string` | `Upload CSV` |
2789
+ | `importLines` | `(count: number) => string` | `Import 3 Lines` |
2790
+ | `importing` | `string` | `Importing...` |
2791
+ | `importFailed` | `string` | `Import failed.` |
2792
+ | `enterAtLeastOne` | `(noun: string, title: string) => string` | `Enter at least one {noun}.` (`Enter at least one value.` with no title) |
2793
+ | `allSkipped` | `string` | `All rows skipped.` |
2794
+ | `cancel` | `string` | `Cancel` |
2795
+ | `mapTitle` | `string` | `Map CSV columns to fields` |
2796
+ | `skip` | `string` | `— Skip —` |
2797
+ | `columnOption` | `(column: number, sample: string) => string` | `Column 3 (e.g. {sample})` |
2798
+ | `rowsDetected` | `(count: number) => string` | `3 rows detected` |
2799
+ | `confirmMapping` | `string` | `Confirm Mapping` |
2800
+ | `duplicatesTitle` | `string` | `Duplicate entries detected` |
2801
+ | `duplicatesFound` | `(count: number) => string` | `3 values appear more than once in your import. Choose how to handle each before proceeding.` (`1 value appears…` for one) |
2802
+ | `occurrences` | `(count: number) => string` | `3 occurrences` |
2803
+ | `keepFirst` | `string` | `Keep first` |
2804
+ | `keepLast` | `string` | `Keep last` |
2805
+ | `keepAll` | `string` | `Keep all` |
2806
+ | `skipAll` | `string` | `Skip all` |
2807
+ | `keptDropped` | `(kept: number, dropped: number) => string` | `3 kept · 3 dropped` |
2808
+ | `proceed` | `string` | `Proceed` |
2809
+ | `duplicatesMerged` | `(count: number) => string` | `3 values appeared more than once. Each is merged into a single line with its quantity summed — review before proceeding.` (`1 value appeared…` for one) |
2810
+ | `mergedFrom` | `string` | `Merged from` |
2811
+ | `mergedRows` | `(count: number) => string` | `3 rows` |
2812
+ | `mergeSummary` | `(rows: number, lines: number) => string` | `3 duplicate rows → 3 merged lines` (`… → 1 merged line` for one) |
2813
+
2814
+ </details>
2815
+
2816
+ <details><summary><code>preview</code> — 29 keys</summary>
2817
+
2818
+ | Key | Type | English default |
2819
+ |---|---|---|
2820
+ | `windowTitle` | `(name: string) => string` | `{name} - Preview` |
2821
+ | `untitled` | `string` | `Untitled` |
2822
+ | `open` | `string` | `Open` |
2823
+ | `formats` | `string` | `PDF · DXF · 3D · Images` |
2824
+ | `dropHere` | `(open: string) => string` | `Drop a file here, or click {open}.` |
2825
+ | `supportedFormats` | `string` | `Supported formats` |
2826
+ | `formatPdf` | `string` | `multi-page document viewer` |
2827
+ | `formatDxf` | `(packageName: string) => string` | `vector CAD drawings (optional {packageName} peer dep)` |
2828
+ | `format3d` | `(packageName: string) => string` | `3D models (optional {packageName} peer dep)` |
2829
+ | `formatImage` | `string` | `raster images` |
2830
+ | `dwgNote` | `string` | `DWG files need to be converted to PDF or DXF first (server-side).` |
2831
+ | `dropToOpen` | `string` | `Drop to open` |
2832
+ | `dwgUnsupported` | `string` | `DWG files need server-side conversion. Convert to PDF or DXF first.` |
2833
+ | `unsupportedType` | `(extension: string) => string` | `Unsupported file type: .{extension}` (`.unknown` with none) |
2834
+ | `converting` | `string` | `Converting file` |
2835
+ | `download` | `string` | `Download` |
2836
+ | `email` | `string` | `Email` |
2837
+ | `howToNavigate` | `string` | `How to navigate` |
2838
+ | `stopMeasuring` | `string` | `Stop measuring (Esc)` |
2839
+ | `scrollToZoom` | `string` | `Scroll to zoom` |
2840
+ | `closePanel` | `string` | `Close` |
2841
+ | `annotate` | `string` | `Annotate` |
2842
+ | `annotateHint` | `string` | `Annotate this image` |
2843
+ | `view` | `string` | `View` |
2844
+ | `viewHint` | `string` | `Back to viewer` |
2845
+ | `copy` | `string` | `Copy` |
2846
+ | `save` | `string` | `Save` |
2847
+ | `imageFailed` | `string` | `Failed to load image.` |
2848
+ | `downloadFailed` | `string` | `Download failed — couldn't reach the file.` |
2849
+
2850
+ </details>
2851
+
2852
+ <details><summary><code>drawing</code> — 49 keys</summary>
2853
+
2854
+ | Key | Type | English default |
2855
+ |---|---|---|
2856
+ | `loading` | `string` | `Loading drawing…` |
2857
+ | `notInstalled` | `string` | `dxf-viewer is not installed in this app.` |
2858
+ | `renderFailed` | `string` | `Failed to render DXF.` |
2859
+ | `layers` | `string` | `Layers` |
2860
+ | `layersHint` | `string` | `Toggle layer visibility` |
2861
+ | `allLayers` | `string` | `All` |
2862
+ | `noLayers` | `string` | `None` |
2863
+ | `measure` | `string` | `Measure` |
2864
+ | `measureHint` | `string` | `Measure distance — click two points on the drawing, or type DI / DIM below` |
2865
+ | `auto` | `string` | `Auto` |
2866
+ | `autoHint` | `string` | `Auto — AutoCAD DIMLINEAR: measures ΔX or ΔY, whichever is larger between the two picks` |
2867
+ | `horizontalHint` | `string` | `Horizontal — distance along the X axis between two picks (AutoCAD DIMLINEAR horizontal)` |
2868
+ | `verticalHint` | `string` | `Vertical — distance along the Y axis between two picks (AutoCAD DIMLINEAR vertical)` |
2869
+ | `point` | `string` | `Point` |
2870
+ | `pointHint` | `string` | `Point — straight-line (Euclidean) distance between two picks (AutoCAD DIST)` |
2871
+ | `fixX` | `string` | `fix Δx` |
2872
+ | `fixY` | `string` | `fix Δy` |
2873
+ | `fixHint` | `string` | `Lock the second pick's axis coord to first pick + this value (mm). The reported measurement becomes the perpendicular distance.` |
2874
+ | `clearFixed` | `string` | `Clear fixed distance` |
2875
+ | `horizontalDistance` | `(auto: boolean) => string` | `Horizontal distance (Δx) between the two picked points` (plus ` — Auto resolved to the X axis` when `auto`) |
2876
+ | `verticalDistance` | `(auto: boolean) => string` | `Vertical distance (Δy) between the two picked points` (plus ` — Auto resolved to the Y axis` when `auto`) |
2877
+ | `straightDistance` | `string` | `Straight-line distance between the two picked points` |
2878
+ | `fit` | `string` | `Fit` |
2879
+ | `fitHint` | `string` | `Fit drawing to view` |
2880
+ | `dragToPan` | `string` | `Drag to pan` |
2881
+ | `fitToReset` | `string` | `Fit to reset` |
2882
+ | `typeToMeasure` | `(commands: string) => string` | `Type {commands} to measure` |
2883
+ | `commandPlaceholder` | `string` | `Type a command — DI, DIM, H, V, Z, LA (? for help)` |
2884
+ | `commandHelp` | `string` | `Commands: DI distance · DIM/DLI linear dim · H / V force axis · <number> lock Δ · U undo pick · Z fit · LA layers · Esc exit` |
2885
+ | `echoDistance` | `(distance: string, deltaX: string, deltaY: string) => string` | `Distance = {distance} ΔX = {deltaX} ΔY = {deltaY}` |
2886
+ | `echoLinear` | `(distance: string, axis: string) => string` | `Linear dimension = {distance} ({axis})` |
2887
+ | `echoLocked` | `(axis: string, distance: string, lockedAxis: string, locked: string) => string` | `{axis} = {distance} with {lockedAxis} locked to {locked}` |
2888
+ | `axisLocked` | `(axis: string, distance: string) => string` | `{axis} locked to {distance} — the label shows the perpendicular distance` |
2889
+ | `fixedCleared` | `string` | `Fixed distance cleared.` |
2890
+ | `fixedNeedsAxis` | `string` | `Fixed distances apply in H or V mode — type H or V first.` |
2891
+ | `echoDist` | `string` | `DIST — click two points; straight-line distance (Esc to exit)` |
2892
+ | `echoDimLinear` | `string` | `DIMLINEAR — click two points; measures ΔX or ΔY, whichever is larger (H / V to force)` |
2893
+ | `echoHorizontal` | `string` | `Horizontal — ΔX between the two picks` |
2894
+ | `echoVertical` | `string` | `Vertical — ΔY between the two picks` |
2895
+ | `echoAuto` | `string` | `Auto (DIMLINEAR) — measures along the dominant axis of the two picks` |
2896
+ | `measureOn` | `string` | `Measure on — click two points.` |
2897
+ | `measureOff` | `string` | `Measure off.` |
2898
+ | `pickRemoved` | `string` | `Last pick removed.` |
2899
+ | `zoomExtents` | `string` | `Zoom extents.` |
2900
+ | `layersToggled` | `string` | `Layer panel toggled.` |
2901
+ | `measurementCleared` | `string` | `Measurement cleared.` |
2902
+ | `readOnly` | `(command: string) => string` | `{command} is a drawing command — Preview is a read-only viewer. Measuring: DI, DIM, H, V (? for help)` |
2903
+ | `unknownCommand` | `(command: string) => string` | `Unknown command "{command}" — try DI, DIM, H, V, Z, LA (? for help)` |
2904
+ | `cancelled` | `string` | `*Cancel*` |
2905
+
2906
+ </details>
2907
+
2908
+ <details><summary><code>model</code> — 53 keys</summary>
2909
+
2910
+ | Key | Type | English default |
2911
+ |---|---|---|
2912
+ | `loading` | `string` | `Loading 3D model…` |
2913
+ | `stepNote` | `string` | `STEP files load OpenCascade WASM (~5 MB) on first use.` |
2914
+ | `notInstalled` | `string` | `online-3d-viewer is not installed in this app. Add it to enable 3D file viewing.` |
2915
+ | `loadFailed` | `string` | `Failed to load 3D model.` |
2916
+ | `rootNode` | `string` | `Root` |
2917
+ | `node` | `string` | `Node` |
2918
+ | `collapse` | `string` | `Collapse` |
2919
+ | `expand` | `string` | `Expand` |
2920
+ | `fitToView` | `string` | `Fit to view` |
2921
+ | `hide` | `string` | `Hide` |
2922
+ | `show` | `string` | `Show` |
2923
+ | `isometric` | `string` | `ISO` |
2924
+ | `isometricView` | `string` | `Isometric view` |
2925
+ | `top` | `string` | `TOP` |
2926
+ | `topView` | `string` | `Top view` |
2927
+ | `front` | `string` | `FRT` |
2928
+ | `frontView` | `string` | `Front view` |
2929
+ | `side` | `string` | `SDE` |
2930
+ | `sideView` | `string` | `Side view` |
2931
+ | `perspective` | `string` | `Perspective` |
2932
+ | `orthographic` | `string` | `Orthographic` |
2933
+ | `toPerspective` | `string` | `Switch to perspective view` |
2934
+ | `toOrthographic` | `string` | `Switch to orthographic view` |
2935
+ | `snapshot` | `string` | `Save snapshot as PNG` |
2936
+ | `measureHint` | `string` | `Measure distance — click two points on the model` |
2937
+ | `point` | `string` | `Point` |
2938
+ | `pointHint` | `string` | `Point — measure straight-line distance between two picked points` |
2939
+ | `perpendicularHint` | `string` | `Perpendicular — pick two surfaces and measure the perpendicular gap between them` |
2940
+ | `straightDistance` | `string` | `Straight-line distance between the two picked points` |
2941
+ | `perpendicularDistance` | `string` | `Perpendicular distance between the two picked surfaces` |
2942
+ | `meshesHint` | `string` | `Toggle meshes panel` |
2943
+ | `displayHint` | `string` | `Toggle display panel` |
2944
+ | `downloadOriginal` | `string` | `Download original file` |
2945
+ | `meshes` | `string` | `Meshes` |
2946
+ | `readingModel` | `string` | `Reading model…` |
2947
+ | `noStructure` | `string` | `No structure available` |
2948
+ | `allVisible` | `string` | `All visible` |
2949
+ | `hiddenCount` | `(count: number) => string` | `3 hidden` |
2950
+ | `dragToRotate` | `string` | `Drag to rotate` |
2951
+ | `rightDragToPan` | `string` | `Right-click drag to pan` |
2952
+ | `display` | `string` | `Model Display` |
2953
+ | `backgroundColor` | `string` | `Background Color` |
2954
+ | `showEdges` | `string` | `Show Edges` |
2955
+ | `edgeColor` | `string` | `Edge Color` |
2956
+ | `edgeThreshold` | `string` | `Edge Threshold` |
2957
+ | `sectionView` | `string` | `Section View` |
2958
+ | `angle` | `string` | `Angle` |
2959
+ | `axis` | `string` | `Axis` |
2960
+ | `flipHint` | `string` | `Flip section direction` |
2961
+ | `flip` | `string` | `flip →` |
2962
+ | `flipped` | `string` | `← flipped` |
2963
+ | `position` | `string` | `Position` |
2964
+ | `resetDisplay` | `string` | `Reset to Default` |
2965
+
2966
+ </details>
2967
+
2968
+ <details><summary><code>annotator</code> — 52 keys</summary>
2969
+
2970
+ | Key | Type | English default |
2971
+ |---|---|---|
2972
+ | `toolSelect` | `string` | `Select / Move` |
2973
+ | `toolDraw` | `string` | `Pen / Draw` |
2974
+ | `toolRect` | `string` | `Rectangle` |
2975
+ | `toolEllipse` | `string` | `Ellipse` |
2976
+ | `toolArrow` | `string` | `Arrow` |
2977
+ | `toolMosaic` | `string` | `Mosaic` |
2978
+ | `toolText` | `string` | `Text` |
2979
+ | `toolCrop` | `string` | `Crop` |
2980
+ | `weight` | `string` | `Weight` |
2981
+ | `radius` | `string` | `Radius` |
2982
+ | `size` | `string` | `Size` |
2983
+ | `padding` | `string` | `Pad` |
2984
+ | `fontSystem` | `string` | `System` |
2985
+ | `fontSerif` | `string` | `Serif` |
2986
+ | `fontMono` | `string` | `Mono` |
2987
+ | `fontCursive` | `string` | `Cursive` |
2988
+ | `bold` | `string` | `Bold` |
2989
+ | `boldLetter` | `string` | `B` |
2990
+ | `italic` | `string` | `Italic` |
2991
+ | `italicLetter` | `string` | `I` |
2992
+ | `underline` | `string` | `Underline` |
2993
+ | `underlineLetter` | `string` | `U` |
2994
+ | `border` | `string` | `Border` |
2995
+ | `borderColor` | `string` | `Text-box border color` |
2996
+ | `addBorder` | `string` | `Add a border` |
2997
+ | `removeBorder` | `string` | `Remove border` |
2998
+ | `fill` | `string` | `Fill` |
2999
+ | `fillColor` | `string` | `Text-box background color` |
3000
+ | `addFill` | `string` | `Add a background fill` |
3001
+ | `removeFill` | `string` | `Remove fill` |
3002
+ | `add` | `string` | `Add` |
3003
+ | `zoomOut` | `string` | `Zoom out` |
3004
+ | `zoomIn` | `string` | `Zoom in` |
3005
+ | `fit` | `string` | `Fit` |
3006
+ | `fitHint` | `string` | `Fit to area` |
3007
+ | `undo` | `string` | `Undo` |
3008
+ | `applyCrop` | `string` | `Apply Crop` |
3009
+ | `cancel` | `string` | `Cancel` |
3010
+ | `apply` | `string` | `Apply` |
3011
+ | `hintSelected` | `string` | `Drag to move. Drag a corner to resize. Delete / Backspace removes. Click outside to deselect.` |
3012
+ | `hintSelect` | `string` | `Tap a shape to select. Double-click text to edit.` |
3013
+ | `hintText` | `string` | `Click to drop a text label.` |
3014
+ | `hintCrop` | `string` | `Drag a rectangle to set the crop region.` |
3015
+ | `hintDraw` | `string` | `Drag to draw freehand.` |
3016
+ | `hintShape` | `string` | `Drag on the image to draw.` |
3017
+ | `textPlaceholder` | `string` | `Type then Enter…` |
3018
+ | `loadFailed` | `string` | `Failed to load image` |
3019
+ | `exportFailed` | `string` | `Failed to export` |
3020
+ | `clipboardUnsupported` | `string` | `Clipboard images not supported in this browser` |
3021
+ | `copyFailed` | `string` | `Failed to copy` |
3022
+ | `copied` | `string` | `Copied to clipboard` |
3023
+ | `copyRefused` | `string` | `Copy failed (clipboard permission?)` |
3024
+
3025
+ </details>
3026
+
3027
+ <details><summary><code>attachment</code> — 7 keys</summary>
3028
+
3029
+ | Key | Type | English default |
3030
+ |---|---|---|
3031
+ | `fallbackName` | `string` | `attachment` |
3032
+ | `noLink` | `string` | `This attachment has no download link.` |
3033
+ | `spreadsheetFailed` | `string` | `Could not open the spreadsheet — opening the file instead.` |
3034
+ | `workbookUnavailable` | `string` | `Spreadsheet preview is unavailable for this file type. Opening the file instead.` |
3035
+ | `noViewer` | `string` | `Opening this file outside the app — no viewer can show it here.` |
3036
+ | `loading` | `string` | `LOADING FILE` |
3037
+ | `loadFailed` | `string` | `Failed to load this file.` |
3038
+
3039
+ </details>
3040
+
3041
+ <details><summary><code>aboutApp</code> — 10 keys</summary>
3042
+
3043
+ | Key | Type | English default |
3044
+ |---|---|---|
3045
+ | `title` | `(name: string) => string` | `About {name}` |
3046
+ | `version` | `(version: string) => string` | `Version {version}` |
3047
+ | `partOf` | `(shell: string) => string` | `Part of the {shell} desktop environment` |
3048
+ | `shellVersion` | `(version: string) => string` | `shell v{version}` |
3049
+ | `spreadsheet` | `string` | `Multi-sheet spreadsheet editor with CSV / TSV import and export.` |
3050
+ | `notepad` | `string` | `Color-coded notes with checklists, desktop stickies and entity autolinking.` |
3051
+ | `documents` | `string` | `Letter-page editor for Word documents and plain-text files — images, lists, alignment.` |
3052
+ | `preview` | `string` | `Viewer for PDF documents, images, DXF drawings and 3D models — CAD-style measuring with object snap and an AutoCAD-like command bar.` |
3053
+ | `files` | `string` | `Personal file manager with folders, uploads, quota, trash and desktop shortcut folders.` |
3054
+ | `browser` | `string` | `Minimal web browser with bookmarks, history and navigation bar.` |
3055
+
3056
+ </details>
3057
+
2681
3058
  ### Brand surfaces — `efficient-shell/brand.css`
2682
3059
 
2683
3060
  For output that is not a portal window — a report, a published artifact, a
@@ -1,29 +1,29 @@
1
- import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-4PCIZFDR.js";import{WindowTitle as r}from"./chunk-TZ2BPFCT.js";import"./chunk-DSSLOQDW.js";import"./chunk-ZOPYAOUP.js";import"./chunk-MFXG5BWL.js";import"./chunk-YJRC6IKD.js";import"./chunk-5A7MWTXX.js";import"./chunk-OGXU7QFW.js";import{confirm as n}from"./chunk-XJYXKO7K.js";import"./chunk-AA4TMQOS.js";import"./chunk-AFYQTVZO.js";import"./chunk-HZZNJHRH.js";import"./chunk-X4FJ54PP.js";import"./chunk-D65T4H6J.js";import"./chunk-3YTHR7IC.js";import"./chunk-YKZHOXI4.js";import{useRef as a,useEffect as i,useState as s}from"react";import{jsxs as l,jsx as c,Fragment as m}from"react/jsx-runtime";var d="react-os-shell:browser-bookmarks",u="react-os-shell:browser-homepage",h="https://en.wikipedia.org/wiki/Main_Page",p=[{label:"Wikipedia",url:"https://en.wikipedia.org/wiki/Main_Page"},{label:"DevDocs",url:"https://devdocs.io"},{label:"Example",url:"https://example.com"}],g=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 b(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&&g.has(t[2].toLowerCase())}(t)?"https://"+t:"https://duckduckgo.com/?q="+encodeURIComponent(t):""}var k=["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 f(){if("undefined"==typeof window)return p;try{const e=localStorage.getItem(d);if(!e)return p;const t=JSON.parse(e);if(Array.isArray(t)&&t.every(e=>"string"==typeof e?.url))return t}catch{}return p}function x(){return"undefined"==typeof window?h:localStorage.getItem(u)||h}function w(){const m=a(void 0);void 0===m.current&&(m.current=e()),i(()=>{null!=m.current&&t(m.current)},[]);const h=m.current?b(m.current.url):"",[p,g]=s(x),[k,w]=s(h||p),[N,L]=s(k),[C,j]=s([k]),[z,M]=s(0),[W,H]=s(0),[R,S]=s(f),[A,B]=s(!1),[O,T]=s(null),D=a(null),P=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(R))}catch{}},[R]);const E=e=>{const t=b(e);t&&(w(t),L(t),j(e=>{const o=e.slice(0,z+1);return o.push(t),o}),M(e=>e+1),B(!1))},F=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},I=()=>{const e=O?.trim();e?(S(t=>[...t,{label:e,url:k}]),T(null)):T(null)};i(()=>{if(null===O)return;D.current?.focus(),D.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||T(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==O]);const X=e=>{S(t=>t.filter((t,o)=>o!==e))},U=z>0,J=z<C.length-1,K=R.some(e=>e.url===k),Y="p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";/* @__PURE__ */
1
+ import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-RQOP5JAJ.js";import{WindowTitle as r}from"./chunk-N6STBYXR.js";import"./chunk-DSSLOQDW.js";import"./chunk-KVOFUFPP.js";import"./chunk-BSJIBRWC.js";import"./chunk-CIXQKCFA.js";import"./chunk-5A7MWTXX.js";import"./chunk-OGXU7QFW.js";import{confirm as n}from"./chunk-ZAE6ROV7.js";import"./chunk-AA4TMQOS.js";import"./chunk-AFYQTVZO.js";import"./chunk-HZZNJHRH.js";import"./chunk-X4FJ54PP.js";import"./chunk-D65T4H6J.js";import"./chunk-J3LIIIHJ.js";import"./chunk-C3QOHMR6.js";import"./chunk-YKZHOXI4.js";import{useRef as a,useEffect as i,useState as s}from"react";import{jsxs as l,jsx as c,Fragment as m}from"react/jsx-runtime";var d="react-os-shell:browser-bookmarks",u="react-os-shell:browser-homepage",h="https://en.wikipedia.org/wiki/Main_Page",p=[{label:"Wikipedia",url:"https://en.wikipedia.org/wiki/Main_Page"},{label:"DevDocs",url:"https://devdocs.io"},{label:"Example",url:"https://example.com"}],g=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 b(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&&g.has(t[2].toLowerCase())}(t)?"https://"+t:"https://duckduckgo.com/?q="+encodeURIComponent(t):""}var k=["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 f(){if("undefined"==typeof window)return p;try{const e=localStorage.getItem(d);if(!e)return p;const t=JSON.parse(e);if(Array.isArray(t)&&t.every(e=>"string"==typeof e?.url))return t}catch{}return p}function x(){return"undefined"==typeof window?h:localStorage.getItem(u)||h}function w(){const m=a(void 0);void 0===m.current&&(m.current=e()),i(()=>{null!=m.current&&t(m.current)},[]);const h=m.current?b(m.current.url):"",[p,g]=s(x),[k,w]=s(h||p),[N,L]=s(k),[j,C]=s([k]),[z,M]=s(0),[R,S]=s(0),[W,H]=s(f),[A,B]=s(!1),[O,I]=s(null),E=a(null),T=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(W))}catch{}},[W]);const D=e=>{const t=b(e);t&&(w(t),L(t),C(e=>{const o=e.slice(0,z+1);return o.push(t),o}),M(e=>e+1),B(!1))},F=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},J=()=>{const e=O?.trim();e?(H(t=>[...t,{label:e,url:k}]),I(null)):I(null)};i(()=>{if(null===O)return;E.current?.focus(),E.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||I(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==O]);const P=e=>{H(t=>t.filter((t,o)=>o!==e))},X=z>0,Q=z<j.length-1,U=W.some(e=>e.url===k),V="p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";/* @__PURE__ */
2
2
  return l("div",{className:"relative flex flex-col h-full bg-white",children:[
3
3
  /* @__PURE__ */c(r,{title:`Browser - ${v(k)}`}),
4
4
  /* @__PURE__ */c(o,{app:"browser"}),
5
5
  /* @__PURE__ */l("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__ */c("button",{onClick:()=>{if(z>0){const e=z-1;M(e),w(C[e]),L(C[e]),B(!1)}},disabled:!U,className:Y,title:"Back",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15.75 19.5L8.25 12l7.5-7.5"})})}),
7
- /* @__PURE__ */c("button",{onClick:()=>{if(z<C.length-1){const e=z+1;M(e),w(C[e]),L(C[e]),B(!1)}},disabled:!J,className:Y,title:"Forward",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.25 4.5l7.5 7.5-7.5 7.5"})})}),
8
- /* @__PURE__ */c("button",{onClick:()=>H(e=>e+1),className:Y,title:"Refresh",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36"})})}),
9
- /* @__PURE__ */c("button",{onClick:()=>E(p),className:Y,title:"Home",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0l8.954 8.955M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"})})}),
10
- /* @__PURE__ */c("form",{onSubmit:e=>{e.preventDefault(),E(N)},className:"flex-1 flex items-center mx-1",children:/* @__PURE__ */l("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:[
6
+ /* @__PURE__ */c("button",{onClick:()=>{if(z>0){const e=z-1;M(e),w(j[e]),L(j[e]),B(!1)}},disabled:!X,className:V,title:"Back",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15.75 19.5L8.25 12l7.5-7.5"})})}),
7
+ /* @__PURE__ */c("button",{onClick:()=>{if(z<j.length-1){const e=z+1;M(e),w(j[e]),L(j[e]),B(!1)}},disabled:!Q,className:V,title:"Forward",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.25 4.5l7.5 7.5-7.5 7.5"})})}),
8
+ /* @__PURE__ */c("button",{onClick:()=>S(e=>e+1),className:V,title:"Refresh",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36"})})}),
9
+ /* @__PURE__ */c("button",{onClick:()=>D(p),className:V,title:"Home",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0l8.954 8.955M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"})})}),
10
+ /* @__PURE__ */c("form",{onSubmit:e=>{e.preventDefault(),D(N)},className:"flex-1 flex items-center mx-1",children:/* @__PURE__ */l("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
11
  /* @__PURE__ */c("span",{className:"px-2 text-gray-400 text-xs",children:k.startsWith("https://")?"🔒":"⚠️"}),
12
12
  /* @__PURE__ */c("input",{type:"text",value:N,onChange:e=>L(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…"}),k!==N&&/* @__PURE__ */c("button",{type:"button",onClick:()=>L(k),className:"px-1.5 text-[10px] text-gray-400 hover:text-gray-700",title:"Reset to current URL",children:"×"})]})}),
13
- /* @__PURE__ */c("button",{"data-bookmark-popover":!0,onClick:()=>K?X(R.findIndex(e=>e.url===k)):void T(v(k)),className:Y+" "+(K?"text-yellow-500":""),title:K?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:K?"currentColor":"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"})})}),
14
- /* @__PURE__ */c("button",{onClick:F,className:Y,title:"Open in new tab",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25"})})}),
15
- /* @__PURE__ */c("button",{onClick:()=>B(e=>!e),className:Y,title:"Embedding help",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"})})})]}),null!==O&&/* @__PURE__ */l("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:[
13
+ /* @__PURE__ */c("button",{"data-bookmark-popover":!0,onClick:()=>U?P(W.findIndex(e=>e.url===k)):void I(v(k)),className:V+" "+(U?"text-yellow-500":""),title:U?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:U?"currentColor":"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"})})}),
14
+ /* @__PURE__ */c("button",{onClick:F,className:V,title:"Open in new tab",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25"})})}),
15
+ /* @__PURE__ */c("button",{onClick:()=>B(e=>!e),className:V,title:"Embedding help",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"})})})]}),null!==O&&/* @__PURE__ */l("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
16
  /* @__PURE__ */c("div",{className:"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1",children:"Bookmark this page"}),
17
17
  /* @__PURE__ */c("div",{className:"text-[11px] text-gray-400 truncate mb-2 font-mono",title:k,children:k}),
18
- /* @__PURE__ */c("input",{ref:D,type:"text",value:O,onChange:e=>T(e.target.value),onKeyDown:e=>{"Enter"===e.key?I():"Escape"===e.key&&T(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"}),
18
+ /* @__PURE__ */c("input",{ref:E,type:"text",value:O,onChange:e=>I(e.target.value),onKeyDown:e=>{"Enter"===e.key?J():"Escape"===e.key&&I(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
19
  /* @__PURE__ */l("div",{className:"flex justify-end gap-1 mt-2",children:[
20
- /* @__PURE__ */c("button",{onClick:()=>T(null),className:"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded",children:"Cancel"}),
21
- /* @__PURE__ */c("button",{onClick:I,disabled:!O.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__ */l("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===R.length&&/* @__PURE__ */c("span",{className:"text-[11px] text-gray-400 italic px-2",children:"No bookmarks yet — star the address bar to add one."}),R.map((e,t)=>/* @__PURE__ */l("button",{onClick:()=>E(e.url),onContextMenu:async o=>{o.preventDefault();await n({title:"Remove bookmark",message:`"${e.label}" will be removed from your bookmarks.`,confirmLabel:"Remove",variant:"danger"})&&X(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:[
20
+ /* @__PURE__ */c("button",{onClick:()=>I(null),className:"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded",children:"Cancel"}),
21
+ /* @__PURE__ */c("button",{onClick:J,disabled:!O.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__ */l("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===W.length&&/* @__PURE__ */c("span",{className:"text-[11px] text-gray-400 italic px-2",children:"No bookmarks yet — star the address bar to add one."}),W.map((e,t)=>/* @__PURE__ */l("button",{onClick:()=>D(e.url),onContextMenu:async o=>{o.preventDefault();await n({title:"Remove bookmark",message:`"${e.label}" will be removed from your bookmarks.`,confirmLabel:"Remove",variant:"danger"})&&P(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
23
  /* @__PURE__ */c("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
24
  /* @__PURE__ */c("div",{className:"flex-1"}),
25
25
  /* @__PURE__ */c("button",{onClick:()=>{g(k);try{localStorage.setItem(u,k)}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__ */c("div",{className:"flex-1 relative min-h-0 bg-gray-50",children:/* @__PURE__ */c(y,{url:k,iframeKey:W,iframeRef:P,openExternal:F,showHelp:A,dismissHelp:()=>B(!1)})})]})}function v(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return e}}function y({url:e,iframeKey:t,iframeRef:o,openExternal:r,showHelp:n,dismissHelp:a}){const[d,u]=s(!1);i(()=>{u(!1)},[e]);return function(e){try{const t=new URL(e).hostname.toLowerCase();return k.some(e=>t===e||t.endsWith("."+e))}catch{return!1}}(e)&&!d?/* @__PURE__ */c("div",{className:"absolute inset-0 flex items-center justify-center bg-white p-8",children:/* @__PURE__ */l("div",{className:"max-w-md text-center",children:[
26
+ /* @__PURE__ */c("div",{className:"flex-1 relative min-h-0 bg-gray-50",children:/* @__PURE__ */c(y,{url:k,iframeKey:R,iframeRef:T,openExternal:F,showHelp:A,dismissHelp:()=>B(!1)})})]})}function v(e){try{return new URL(e).hostname.replace(/^www\./,"")}catch{return e}}function y({url:e,iframeKey:t,iframeRef:o,openExternal:r,showHelp:n,dismissHelp:a}){const[d,u]=s(!1);i(()=>{u(!1)},[e]);return function(e){try{const t=new URL(e).hostname.toLowerCase();return k.some(e=>t===e||t.endsWith("."+e))}catch{return!1}}(e)&&!d?/* @__PURE__ */c("div",{className:"absolute inset-0 flex items-center justify-center bg-white p-8",children:/* @__PURE__ */l("div",{className:"max-w-md text-center",children:[
27
27
  /* @__PURE__ */c("svg",{className:"h-14 w-14 mx-auto text-gray-300 mb-3",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L21 21M5.636 5.636L3 3m9 9a9 9 0 110-18 9 9 0 010 18z"})}),
28
28
  /* @__PURE__ */l("h3",{className:"text-base font-semibold text-gray-800 mb-1",children:[v(e)," can't be embedded"]}),
29
29
  /* @__PURE__ */l("p",{className:"text-sm text-gray-500 mb-4",children:["This site sends an ",
@@ -0,0 +1,29 @@
1
+ import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-SVO3ES2E.js";import{useWidgetSettings as n}from"./chunk-N6STBYXR.js";import"./chunk-DSSLOQDW.js";import"./chunk-KVOFUFPP.js";import"./chunk-CIXQKCFA.js";import"./chunk-5A7MWTXX.js";import"./chunk-OGXU7QFW.js";import"./chunk-ZAE6ROV7.js";import"./chunk-AA4TMQOS.js";import"./chunk-AFYQTVZO.js";import"./chunk-HZZNJHRH.js";import"./chunk-X4FJ54PP.js";import"./chunk-D65T4H6J.js";import"./chunk-J3LIIIHJ.js";import"./chunk-C3QOHMR6.js";import"./chunk-YKZHOXI4.js";import{useState as r,useRef as l,useCallback as o,useEffect as i}from"react";import{jsxs as a,Fragment as c,jsx as s}from"react/jsx-runtime";var u="calc_appearance";function d(){const[d,h]=r("0"),[m,k]=r(null),[b,p]=r(null),[g,v]=r(!1),[x,y]=r(""),[N,f]=r([]),[C,$]=r(!1),[j,w]=r(()=>e(u)),[S,E]=r(!1),[F,O]=r(j),T=l(null);n(o(()=>{O({...j}),E(!0)},[j]));const A=o(e=>{y(""),h(t=>g||"0"===t?(v(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[g]),L=o(()=>{h("0"),k(null),p(null),v(!1)},[]),H=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}},[]),W=o(e=>{const t=parseFloat(d);if(null!==m&&b&&!g){const e=H(m,t,b);h(String(e)),k(e),f(n=>[`${m} ${b} ${t} = ${e}`,...n].slice(0,20))}else k(t);p(e),v(!0)},[d,m,b,g,H]),X=o(()=>{if(null===m||!b)return;const e=parseFloat(d),t=H(m,e,b),n=`${m} ${b} ${e} =`;f(e=>[`${n} ${t}`,...e].slice(0,20)),y(n),h(String(t)),k(null),p(null),v(!0)},[d,m,b,H]),I=o(()=>{h(e=>String(parseFloat(e)/100))},[]),B=o(()=>{h(e=>e.startsWith("-")?e.slice(1):"0"===e?e:"-"+e)},[]);i(()=>{const e=e=>{const t=e.target.tagName;"INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t&&(e.key>="0"&&e.key<="9"?A(e.key):"."===e.key?A("."):"+"===e.key?W("+"):"-"===e.key?W("-"):"*"===e.key?W("×"):"/"===e.key?(e.preventDefault(),W("÷")):"Enter"===e.key||"="===e.key?("Enter"===e.key&&e.target instanceof Node&&T.current?.contains(e.target)&&e.preventDefault(),X()):"Escape"===e.key?L():"Backspace"===e.key?h(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&I())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[A,W,X,L,I]);const J="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",M=`${J} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,Q=`${J} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,D=`${J} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,P=`${J} bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800`;/* @__PURE__ */
2
+ return a(c,{children:[
3
+ /* @__PURE__ */a("div",{ref:T,className:"flex flex-col h-full",style:{opacity:j.activeOpacity/100,backdropFilter:j.activeBlur>0?`blur(${j.activeBlur}px)`:void 0},children:[
4
+ /* @__PURE__ */a("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__ */s("div",{className:"flex flex-col justify-end flex-1 overflow-hidden",children:N.slice(0,3).reverse().map((e,t)=>/* @__PURE__ */s("div",{className:"text-[11px] text-slate-400 text-right font-mono truncate",children:e},t))}),(x||b&&null!==m)&&/* @__PURE__ */s("div",{className:"text-base text-slate-600 text-right font-mono",children:x||`${m} ${b} ${g?"":d}`}),
6
+ /* @__PURE__ */a("div",{className:"flex items-center gap-2",children:[
7
+ /* @__PURE__ */s("button",{onClick:()=>{navigator.clipboard.writeText(d),$(!0),setTimeout(()=>$(!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__ */s("svg",C?{className:"h-5 w-5 text-green-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */s("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M5 13l4 4L19 7"})}:{className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */s("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"})})}),
8
+ /* @__PURE__ */s("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)})(d)})]})]}),
9
+ /* @__PURE__ */a("div",{className:"grid grid-cols-4 grid-rows-5 gap-1.5 flex-1 min-h-0 p-2",children:[
10
+ /* @__PURE__ */s("button",{onClick:L,className:D,children:"AC"}),
11
+ /* @__PURE__ */s("button",{onClick:B,className:D,children:"+/−"}),
12
+ /* @__PURE__ */s("button",{onClick:I,className:D,children:"%"}),
13
+ /* @__PURE__ */s("button",{onClick:()=>W("÷"),className:`${Q} ${"÷"===b?"ring-2 ring-blue-400":""}`,children:"÷"}),
14
+ /* @__PURE__ */s("button",{onClick:()=>A("7"),className:M,children:"7"}),
15
+ /* @__PURE__ */s("button",{onClick:()=>A("8"),className:M,children:"8"}),
16
+ /* @__PURE__ */s("button",{onClick:()=>A("9"),className:M,children:"9"}),
17
+ /* @__PURE__ */s("button",{onClick:()=>W("×"),className:`${Q} ${"×"===b?"ring-2 ring-blue-400":""}`,children:"×"}),
18
+ /* @__PURE__ */s("button",{onClick:()=>A("4"),className:M,children:"4"}),
19
+ /* @__PURE__ */s("button",{onClick:()=>A("5"),className:M,children:"5"}),
20
+ /* @__PURE__ */s("button",{onClick:()=>A("6"),className:M,children:"6"}),
21
+ /* @__PURE__ */s("button",{onClick:()=>W("-"),className:`${Q} ${"-"===b?"ring-2 ring-blue-400":""}`,children:"−"}),
22
+ /* @__PURE__ */s("button",{onClick:()=>A("1"),className:M,children:"1"}),
23
+ /* @__PURE__ */s("button",{onClick:()=>A("2"),className:M,children:"2"}),
24
+ /* @__PURE__ */s("button",{onClick:()=>A("3"),className:M,children:"3"}),
25
+ /* @__PURE__ */s("button",{onClick:()=>W("+"),className:`${Q} ${"+"===b?"ring-2 ring-blue-400":""}`,children:"+"}),
26
+ /* @__PURE__ */s("button",{onClick:()=>A("0"),className:`${M} col-span-2`,children:"0"}),
27
+ /* @__PURE__ */s("button",{onClick:()=>A("."),className:M,children:"."}),
28
+ /* @__PURE__ */s("button",{onClick:X,className:P,children:"="})]})]}),
29
+ /* @__PURE__ */s(t,{open:S,onClose:()=>E(!1),title:"Calculator Settings",appearance:F,onAppearanceChange:O,onSave:()=>{w(F),localStorage.setItem(u,JSON.stringify(F)),E(!1)}})]})}export{d as default};
@@ -0,0 +1 @@
1
+ export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-ZAE6ROV7.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-J3LIIIHJ.js";import"./chunk-C3QOHMR6.js";