efficient-shell 4.145.0 → 4.147.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 (31) hide show
  1. package/README.md +8 -3
  2. package/dist/{Browser-24YNRTKT.js → Browser-52FZDK3P.js} +14 -14
  3. package/dist/{Calculator-LER6KUQC.js → Calculator-4S44DK45.js} +22 -22
  4. package/dist/{ConfirmDialog-GAYETRMG.js → ConfirmDialog-KJNNVFK7.js} +1 -1
  5. package/dist/{CurrencyConverter-Y35GFDFF.js → CurrencyConverter-TH6ISVZ5.js} +5 -5
  6. package/dist/{Documents-7FYX2CGT.js → Documents-TEV6WUCC.js} +11 -11
  7. package/dist/{Files-RZOML2N6.js → Files-T3VMQAO3.js} +31 -31
  8. package/dist/{Notepad-VVDCBDUA.js → Notepad-LYNVGUHK.js} +9 -9
  9. package/dist/{PomodoroTimer-VAM3AJOX.js → PomodoroTimer-IEZ3ALBW.js} +24 -24
  10. package/dist/{Preview-HZ37D7QJ.js → Preview-SJCMGRUS.js} +5 -5
  11. package/dist/{Spreadsheet-6WX3P6AB.js → Spreadsheet-GR6GJTDP.js} +12 -12
  12. package/dist/{Stock-AUWI3TUX.js → Stock-MYXAUZJY.js} +3 -3
  13. package/dist/{Weather-HU75TH7T.js → Weather-HKCFNPV6.js} +15 -15
  14. package/dist/{WorldClock-T64MDRMJ.js → WorldClock-6XVXM4L2.js} +7 -7
  15. package/dist/apps/index.js +1 -1
  16. package/dist/brand.css +1 -1
  17. package/dist/chunk-6JXLEPRE.js +1 -0
  18. package/dist/{chunk-LVFMK5OQ.js → chunk-D4HWQ3ET.js} +1 -1
  19. package/dist/{chunk-2RHMSFZV.js → chunk-JNL7A5HC.js} +7 -7
  20. package/dist/{chunk-GDSGXDET.js → chunk-NUPXFPQW.js} +1 -1
  21. package/dist/{chunk-RJ4LACFH.js → chunk-NV35RTZK.js} +1 -1
  22. package/dist/{chunk-NBBOFQPL.js → chunk-ZFJH3P24.js} +63 -59
  23. package/dist/{chunk-7DAQ3WVP.js → chunk-ZR72F7TE.js} +24 -24
  24. package/dist/{index-NhR7frRu.d.ts → index-DIQYwgxx.d.ts} +38 -4
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +46 -46
  27. package/dist/page-tabs/index.js +10 -10
  28. package/dist/ui/index.d.ts +1 -1
  29. package/dist/ui/index.js +1 -1
  30. package/package.json +1 -1
  31. package/dist/chunk-TWV42Q3K.js +0 -1
package/README.md CHANGED
@@ -357,6 +357,7 @@ is dragged. The side it ended up on is on the surface as `data-side`.
357
357
  | Action | `{ key, label, onSelect, icon?, danger?, disabled? }` | `<button role="menuitem">`. Every item written before the other kinds existed is one. |
358
358
  | Link | `{ key, label, href, icon?, current?, disabled? }` | A real `<a role="menuitem" href>`, so a middle-click, "Open in new tab" and the status bar's address work. `current` sets `aria-current="page"`. Choosing it closes the menu and lets the click through to the browser or the router. A disabled link has no `href`. |
359
359
  | Radio | `{ key, type: 'radio', label, checked, onSelect, icon?, disabled? }` | `<button role="menuitemradio" aria-checked>`, with a check on the checked one. Consecutive radios form one `role="group"`, named by a label directly above them. |
360
+ | Check box | `{ key, type: 'checkbox', label, checked, onSelect, icon?, disabled? }` | `<button role="menuitemcheckbox" aria-checked>`, a box ticked when on. Choosing it calls `onSelect` (the toggle — you flip `checked`) and the menu STAYS OPEN, focus where it was, so several are ticked in one visit; Escape, Tab or a click elsewhere puts it away. Consecutive check boxes form one `role="group"`, named by a label directly above them. Disable the rest when a limit is reached ("up to eight"). |
360
361
  | Label | `{ key, type: 'label', label }` | A heading (`PopupMenuLabel`). Not focusable. |
361
362
  | Divider | `{ key, type: 'divider' }` | `role="separator"` (`PopupMenuDivider`). |
362
363
 
@@ -368,6 +369,9 @@ trigger button's own classes, so it can look like your nav link or your button.
368
369
  It stays a `<button aria-haspopup="menu" aria-expanded>`, named by its content
369
370
  unless you pass `aria-label`. `menuClassName` is added to the menu's surface,
370
371
  and `minWidth` (pixels, or any CSS length; 180 by default) sets its narrowest.
372
+ `id` and `aria-describedby` go on the trigger, for a menu that is one field of a
373
+ form: the form's `<label htmlFor={id}>` names it (and pressing the label opens
374
+ it), and its hint or error describes it.
371
375
 
372
376
  **Keyboard** (the WAI-ARIA menu button). Enter, Space or ArrowDown on the
373
377
  trigger opens the menu on its first entry, and ArrowUp opens it on its last.
@@ -400,7 +404,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
400
404
  | `PopupMenu`, `PopupMenuItem`, `PopupMenuDivider`, `PopupMenuLabel`, `PopupSubmenu` | Right-click / context-menu primitive; `PopupSubmenu` is a row that opens a nested menu. |
401
405
  | `ShellContextMenu` | The shell-wide right-click menu, already mounted by `Layout` (`<Layout contextMenu={false}>` turns it off). Mount it yourself only on a screen rendered outside the layout. See [Right-click menu](#right-click-menu). |
402
406
  | `DropdownMenu` | A button and the menu it opens, right under it: actions, links (`href`, drawn by `linkAs`), radios, labels and dividers, with shared dismissal and the menu-button keyboard. `align` lines it up with the trigger's left or right edge; `side="top"` suits a trigger in a bottom action bar. See [Dropdown menus](#dropdown-menus). |
403
- | `Dialog`, `Drawer` | A modal sheet that is not a shell window — centred (`Dialog`) or pinned to an edge (`Drawer`, `side` right / left / bottom) — for a till, a routed page or a form: trapped focus, a locked page, Escape and a backdrop click to close (`blocking` turns both off), a close cross when there is no `footer`. `title` names it; `description` is a line under the title that DESCRIBES it to a screen reader — without one the body does, which suits a confirm whose body is the question and not a form, whose every label would be read out. `role="alertdialog"` (Dialog) for a confirmation that interrupts. A heading or note that lives in the body — a form that loads the record its heading names — names and describes it through `aria-labelledby` / `aria-describedby`. Two open at once — the second inside the first, or beside it on `<body>` where a host portals its dialogs — each hold focus, and only the one in front moves Tab (`useFocusTrap` keeps a stack). |
407
+ | `Dialog`, `Drawer` | A modal sheet that is not a shell window — centred (`Dialog`) or pinned to an edge (`Drawer`, `side` right / left / bottom) — for a till, a routed page or a form: trapped focus, a locked page, Escape and a backdrop click to close (`blocking` turns both off), a close cross when there is no `footer`. A `Dialog` is never taller than the screen less its gutter: a longer form — on a phone, most of them — scrolls inside the panel, footer included, and a footer wider than the panel wraps. `title` names it; `description` is a line under the title that DESCRIBES it to a screen reader — without one the body does, which suits a confirm whose body is the question and not a form, whose every label would be read out. `role="alertdialog"` (Dialog) for a confirmation that interrupts. A heading or note that lives in the body — a form that loads the record its heading names — names and describes it through `aria-labelledby` / `aria-describedby`. Two open at once — the second inside the first, or beside it on `<body>` where a host portals its dialogs — each hold focus, and only the one in front moves Tab (`useFocusTrap` keeps a stack). |
404
408
  | `ConfirmProvider`, `confirm` | Imperative `confirm({ title, body })` returning a Promise<boolean>. |
405
409
  | `GlobalSearch` | Cmd-K command palette. Pass `providers: SearchProvider[]` to add results. Portalled to `<body>` on the overlay layer (`Z_LAYERS.overlay`), so it covers every window, pinned or not; opening it closes any open popup (`dismissPopups`). |
406
410
  | `ShortcutHelp` | The keyboard cheatsheet shown on `?`. |
@@ -417,6 +421,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
417
421
  | `SettingRow` | One setting: its name and current value on one baseline, the explanation at full width beneath in a smaller voice. The value never shrinks, so a short badge keeps its line instead of folding into a narrow column. Handles a value that is a control (`controlId` labels it), a read-only fact, a value nobody knows (an em dash in the faint ink, never an empty cell), and a `quiet` row nothing can write yet. `DescriptionList` is the record-detail neighbour and stays that. |
418
422
  | `Button`, `Input`, `Textarea`, `Select`, `Checkbox`, `Radio`, `Switch`, `FormField`, `Label` | Form controls — controlled (`value`/`onChange`); `Input`/`Textarea` forward native props for react-hook-form. `Button` and `Switch` take `disabledReason`: persistent text beside the control wired with `aria-describedby`, never a `title` — a tooltip needs a hover a disabled control does not reliably get. `Switch` also takes `disabledReasonId`, so a panel whose controls are all dead for one reason states it once and points every control at it. A `Select` option carries an optional `description`, rendered as a second muted line **in the open list only** — the closed trigger stays one line, so one explained option cannot change the height of every field in the row. `NativeSelect` (and so `Select` on touch) ignores it: an `<option>` holds text and nothing else. An option also takes `lang` (a BCP 47 tag) when its label is written in another language than the page's — a language picker naming each language in its own words: it goes on the option in the open list, on the native `<option>` and on the closed trigger's label while chosen, so a screen reader and the font fallback treat each name as its own language (WCAG 3.1.2). On the desktop listbox, `title` joins `aria-label` / `aria-labelledby` / `aria-describedby` on the VISIBLE trigger button — it used to ride the native spread onto the `sr-only` `<select>`, where a tooltip has no pointer that can reach it and a fallback name sits on an `aria-hidden` element. `name`, `required` and the forwarded ref stay on the native control, which is what it is for. A `Checkbox` or `Radio` with both a `label` and a `description` is NAMED by the label and DESCRIBED by the description (`aria-labelledby` / `aria-describedby`); the whole row is still its `<label>`, so its words still tick it. |
419
423
  | `buttonClasses`, `iconButtonClasses` | `Button`'s and `IconButton`'s look as a class string, for something that must navigate and so cannot be a `<button>`: `<Link href="/organisations/new" className={buttonClasses({ variant: 'secondary' })}>Add a business</Link>`. Same options and defaults as the component (`variant`, `size`, `block`, `className`), and the components render through these functions, so the two cannot drift. What the string cannot give an `<a>`: a disabled state (`disabled:` never matches an anchor — drop the `href`, add `role="link"` and `aria-disabled="true"`, or render a disabled `Button`), and the cursor (an `<a href>` gets the browser's pointer, a `<button>` the host's preflight; set it once for both). Keep its `inline-flex` — ask for `block` rather than passing a display utility. An icon-only link still needs the `aria-label` `IconButton` would have required. Client references, like every kit function: call them in a `'use client'` file. |
424
+ | `Segmented` | A row of mutually exclusive options, all visible: a button group, or with `name` a real radio group that submits. Named by `label`, or by an element already on the page (`aria-labelledby`, a list row's own heading) and described by another (`aria-describedby`); an option's `title` says on hover what choosing it means. |
420
425
  | `RadioGroup` | One choice from a short visible list, with the group chrome each panel used to rebuild: a `role="radiogroup"` named by its own label (`aria-labelledby`, because `<label for>` cannot name a div), the `hint`/`error`/`required` wiring borrowed from `FormField`, and `orientation` for a row that wraps rather than compresses. The options are real native radios sharing one `name`, which is what gives the group its arrow keys, its disabled-skipping and its single tab stop — all from the user agent, none of it hand-rolled. `value: null` is "nothing chosen yet", not a silent first option. |
421
426
  | `Snippet` | A value the user copies rather than reads — an endpoint, a tenant id, a shell command. Monospace, truncated with the whole value on its `title` (`multiline` wraps instead), and a copy button that flips to a check for two seconds and says "Copied" through an `aria-live` region. `value` is what reaches the clipboard and `children` is what is shown, so a masked key displays masked and copies whole. `symbol` prints a leading glyph that is never copied and has **no default** — a URL has no `$` in front of it. A refused clipboard toasts rather than looking like it worked. Not a read-only `Input`: a value that can only be copied is not a control and should not take a tab stop or invite an edit. `id` and `aria-describedby` land on the COPY BUTTON — the only focusable thing in the row, and a labelable one — so a wrapping `FormField` really does label it and its hint is really announced; with `hideCopyButton` they fall back to the box, because an id that resolves to nothing is not wiring. |
422
427
  | `Kbd` | The badge the shortcut constants (`CMD_ENTER`, `ALT_SHIFT_E`, …) are shown in — a real `<kbd>`, two rungs, `className` layered on so a portal can tint it. It renders the string it is handed; which symbol a platform uses is what the constants already decide. |
@@ -425,7 +430,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
425
430
  | `DatePicker`, `TimePicker`, `DateTimePicker`, `DateRangePicker` | Date/time fields, all careful to speak LOCAL dates and wall-clock times (never `toISOString`). `TimePicker` and `DateTimePicker` wrap the platform's own inputs in the kit's field styling; `TimePicker` hands back an `HH:MM` string — a time of day names no calendar day, so it never invents a Date. **`DatePicker`** opens the kit's `Calendar` in a popover (`native` swaps in the platform's date input). Its value posts from a hidden input that takes `name` and `form`; `required` adds "Required" to the trigger's description (`datePicker.required`; a button may not carry `aria-required`) and drops Clear from the footer (`clearable` overrides either way); `invalid` paints the field, and the reader hears the error message the host links through `aria-describedby` (`FormField` does) — the trigger carries no `aria-invalid`, which a button may not either; Today is offered only when `min`/`max` allow today; `aria-*`, `data-*`, `title`, `tabIndex`, `autoFocus`, `onFocus` and `onBlur` reach the trigger, while what only a text box can use (`readOnly`, `pattern`, `autoComplete`…) applies with `native` alone. Named by a `<label htmlFor={id}>` or `aria-labelledby`, the trigger is described by the date spelled out. A browser never validates a hidden input, so `required` cannot block a submit in the popover. **`DateRangePicker`** is a from/to calendar with presets in one popover: side by side on a desktop; where that does not fit the room the box allows (a phone, a narrow shell window — measured, not a media query), the panel takes the full width between the margins and stacks, the presets a wrapping row of chips above the calendar and From/To one line each. `fullWidth` fills a filter-grid cell instead of shrink-wrapping its label. `id` (on the trigger button, for `<label htmlFor>`), `aria-labelledby` and `aria-label` name the trigger, and the chosen range is then its description ("Period, button, 1 August 2026 to 3 October 2026"). `name={{ from, to }}` posts the applied range as two hidden `YYYY-MM-DD` inputs (`''` when unset), so a GET form or a server action reads it as it read two date inputs. `required` adds "Required" to the trigger's description (`dateRange.required`) and, unless `clearable` is given, removes Clear. `min` / `max` (`YYYY-MM-DD`) bound it as they bound `DatePicker`: days outside are disabled, a preset whose range reaches outside is not offered (none at all on a range that starts today — time off, a booking — and then no Custom either), and with nothing chosen the panel opens on the first month that has a day to pick. Both pickers take `weekStartsOn` (0 Sunday, 1 Monday); without it the week starts where the provider's `locale` says. |
426
431
  | `Card`, `StatCard` | Surface panel (optional header/footer) + dashboard metric tile. |
427
432
  | `Avatar`, `AvatarGroup` | User avatar with initials fallback + status dot; overlapping stack with +N overflow. |
428
- | `Banner` | Static in-flow alert (`tone`: info / success / warning / danger). `action` renders a control at the right edge — after the text, so a screen reader reaches the problem before the remedy, and before the dismiss ×, so "Update card" is never past "close this". Vertically centred against the whole box and `shrink-0`, so a message that wraps does not drag the button down or squeeze it. A banner that names a condition and leaves the fix three menus away is the usual shape of a notice nobody acts on. |
433
+ | `Banner` | Static in-flow alert (`tone`: info / success / warning / danger). `action` renders a control at the right edge — after the text, so a screen reader reaches the problem before the remedy, and before the dismiss ×, so "Update card" is never past "close this". Vertically centred against the words and `shrink-0`, so a message that wraps does not drag the button down or squeeze it — and on a narrow banner (a phone, a narrow column: the words keep at least 12rem) it drops UNDER the words rather than leave them a column one word wide. A banner that names a condition and leaves the fix three menus away is the usual shape of a notice nobody acts on. |
429
434
  | `Tabs`, `Accordion`, `Tooltip` | Controlled tab strip, collapsible sections, frosted hover/focus tooltip. A tooltip's `side` is a preference: near an edge the bubble slides along that side to stay 8 px clear of it, and flips to the opposite side when its own has no room, keeping inside the screen and inside the shell window that owns its trigger (UI-11). It never leaves that box: a bubble wider than the room wraps, and one taller than the room is cut off at it. A small arrow on the edge facing the trigger points at the trigger's centre wherever the bubble ended up, kept clear of the bubble's corners; it is the bubble's own surface (`.rosh-tooltip-arrow` in `ui.css`), solid and seamless under `rosh-reduce-transparency`, and hidden from assistive technology. |
430
435
  | `Stepper` | A linear wizard's progress strip — numbered circles, connectors, `aria-current="step"`. Controlled like Tabs; completed steps are clickable to go back (when `onChange` is wired), upcoming steps never are — moving forward belongs to the wizard's own Continue button, behind its validation. |
431
436
  | `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` and any `data-*` attributes for its `<tr>` — a test's or a stylesheet's hook (`data-testid`, `data-state`). `stackOnNarrow` turns each row into a labelled card on a narrow container — see [DataTable on a narrow screen](#datatable-on-a-narrow-screen). |
@@ -433,7 +438,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
433
438
  | `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. |
434
439
  | `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. |
435
440
  | `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. |
436
- | `Calendar` | Month grid with full keyboard navigation (arrows, Home/End, PageUp/Down) and `role="grid"` semantics. Single or range. The shared grid behind `DatePicker` and `DateRangePicker`. `weekStartsOn` defaults to the provider locale's first day of the week (`firstDayOfWeek`), Sunday without one. |
441
+ | `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. |
437
442
  | `DashboardTemplate`, `DataTablePage`, `FormLayoutPage`, `CheckoutTemplate`, `EmailTemplate`, `ChatTemplate`, `GalleryTemplate`, `AuthScreen`, `ErrorPage` | Zero-prop starter page templates composed from the primitives. |
438
443
  | `ErrorBoundary` | Catches a render crash and shows `ErrorPage` 500 rather than a blank screen. `showDetails` is off by default, so a visitor is never shown the stack; the fallback is `role="alert"`. Takes `onError` for reporting and `resetKeys` to recover on navigation. |
439
444
  | `AppUpdateBanner` | "A new version is available" for a tab that outlived a deploy, without a service worker. Polls the build's `version.json` (a minute apart from a visible tab, never from a hidden one, and once more the moment a hidden tab is shown) and, when the deployed version differs from `currentVersion`, pins a warning banner at the top centre above every window naming both versions with a primary "Refresh now" that reloads. Renders nothing until then. `versionUrl`, `pollMs`, `message`, `onRefresh`. Pair it with `installStaleChunkReload()` for the tab that opens a lazy window before it notices. |
@@ -1,29 +1,29 @@
1
- import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-RJ4LACFH.js";import"./chunk-TWV42Q3K.js";import{WindowTitle as r}from"./chunk-7DAQ3WVP.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-2RHMSFZV.js";import{confirm as n}from"./chunk-LVFMK5OQ.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useRef as a,useEffect as i,useState as l}from"react";import{jsxs as s,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]=l(x),[k,w]=l(h||p),[N,L]=l(k),[C,j]=l([k]),[z,M]=l(0),[W,R]=l(0),[H,B]=l(f),[S,A]=l(!1),[E,D]=l(null),I=a(null),P=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(H))}catch{}},[H]);const T=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),A(!1))},V=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},F=()=>{const e=E?.trim();e?(B(t=>[...t,{label:e,url:k}]),D(null)):D(null)};i(()=>{if(null===E)return;I.current?.focus(),I.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||D(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==E]);const O=e=>{B(t=>t.filter((t,o)=>o!==e))},U=z>0,q=z<C.length-1,J=H.some(e=>e.url===k),K="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-NV35RTZK.js";import"./chunk-6JXLEPRE.js";import{WindowTitle as r}from"./chunk-ZR72F7TE.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-JNL7A5HC.js";import{confirm as n}from"./chunk-D4HWQ3ET.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useRef as a,useEffect as i,useState as l}from"react";import{jsxs as s,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]=l(x),[k,w]=l(h||p),[N,L]=l(k),[C,j]=l([k]),[z,M]=l(0),[R,W]=l(0),[E,H]=l(f),[B,S]=l(!1),[A,T]=l(null),D=a(null),I=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(E))}catch{}},[E]);const P=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),S(!1))},U=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},J=()=>{const e=A?.trim();e?(H(t=>[...t,{label:e,url:k}]),T(null)):T(null)};i(()=>{if(null===A)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!==A]);const O=e=>{H(t=>t.filter((t,o)=>o!==e))},V=z>0,q=z<C.length-1,F=E.some(e=>e.url===k),K="p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";/* @__PURE__ */
2
2
  return s("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__ */s("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]),A(!1)}},disabled:!U,className:K,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]),A(!1)}},disabled:!q,className:K,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:()=>R(e=>e+1),className:K,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:()=>T(p),className:K,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(),T(N)},className:"flex-1 flex items-center mx-1",children:/* @__PURE__ */s("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(C[e]),L(C[e]),S(!1)}},disabled:!V,className:K,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]),S(!1)}},disabled:!q,className:K,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:()=>W(e=>e+1),className:K,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:()=>P(p),className:K,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(),P(N)},className:"flex-1 flex items-center mx-1",children:/* @__PURE__ */s("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:()=>J?O(H.findIndex(e=>e.url===k)):void D(v(k)),className:K+" "+(J?"text-yellow-500":""),title:J?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:J?"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:V,className:K,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:()=>A(e=>!e),className:K,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!==E&&/* @__PURE__ */s("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:()=>F?O(E.findIndex(e=>e.url===k)):void T(v(k)),className:K+" "+(F?"text-yellow-500":""),title:F?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:F?"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:U,className:K,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:()=>S(e=>!e),className:K,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!==A&&/* @__PURE__ */s("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:I,type:"text",value:E,onChange:e=>D(e.target.value),onKeyDown:e=>{"Enter"===e.key?F():"Escape"===e.key&&D(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:D,type:"text",value:A,onChange:e=>T(e.target.value),onKeyDown:e=>{"Enter"===e.key?J():"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"}),
19
19
  /* @__PURE__ */s("div",{className:"flex justify-end gap-1 mt-2",children:[
20
- /* @__PURE__ */c("button",{onClick:()=>D(null),className:"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded",children:"Cancel"}),
21
- /* @__PURE__ */c("button",{onClick:F,disabled:!E.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__ */s("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===H.length&&/* @__PURE__ */c("span",{className:"text-[11px] text-gray-400 italic px-2",children:"No bookmarks yet — star the address bar to add one."}),H.map((e,t)=>/* @__PURE__ */s("button",{onClick:()=>T(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"})&&O(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:()=>T(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:!A.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__ */s("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===E.length&&/* @__PURE__ */c("span",{className:"text-[11px] text-gray-400 italic px-2",children:"No bookmarks yet — star the address bar to add one."}),E.map((e,t)=>/* @__PURE__ */s("button",{onClick:()=>P(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"})&&O(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:V,showHelp:S,dismissHelp:()=>A(!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]=l(!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__ */s("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:I,openExternal:U,showHelp:B,dismissHelp:()=>S(!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]=l(!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__ */s("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__ */s("h3",{className:"text-base font-semibold text-gray-800 mb-1",children:[v(e)," can't be embedded"]}),
29
29
  /* @__PURE__ */s("p",{className:"text-sm text-gray-500 mb-4",children:["This site sends an ",
@@ -1,29 +1,29 @@
1
- import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-GDSGXDET.js";import{useWidgetSettings as n}from"./chunk-7DAQ3WVP.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-2RHMSFZV.js";import"./chunk-LVFMK5OQ.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as l,useCallback as r,useEffect as i}from"react";import{jsxs as o,Fragment as a,jsx as c}from"react/jsx-runtime";var s="calc_appearance";function u(){const[u,d]=l("0"),[h,m]=l(null),[b,k]=l(null),[g,p]=l(!1),[x,v]=l(""),[y,N]=l([]),[f,C]=l(!1),[$,j]=l(()=>e(s)),[w,E]=l(!1),[L,S]=l($);n(r(()=>{S({...$}),E(!0)},[$]));const T=r(e=>{v(""),d(t=>g||"0"===t?(p(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[g]),B=r(()=>{d("0"),m(null),k(null),p(!1)},[]),F=r((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=r(e=>{const t=parseFloat(u);if(null!==h&&b&&!g){const e=F(h,t,b);d(String(e)),m(e),N(n=>[`${h} ${b} ${t} = ${e}`,...n].slice(0,20))}else m(t);k(e),p(!0)},[u,h,b,g,F]),M=r(()=>{if(null===h||!b)return;const e=parseFloat(u),t=F(h,e,b),n=`${h} ${b} ${e} =`;N(e=>[`${n} ${t}`,...e].slice(0,20)),v(n),d(String(t)),m(null),k(null),p(!0)},[u,h,b,F]),A=r(()=>{d(e=>String(parseFloat(e)/100))},[]),D=r(()=>{d(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"?T(e.key):"."===e.key?T("."):"+"===e.key?W("+"):"-"===e.key?W("-"):"*"===e.key?W("×"):"/"===e.key?(e.preventDefault(),W("÷")):"Enter"===e.key||"="===e.key?M():"Escape"===e.key?B():"Backspace"===e.key?d(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&A())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[T,W,M,B,A]);const I="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",P=`${I} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,H=`${I} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,V=`${I} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,J=`${I} bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800`;/* @__PURE__ */
1
+ import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-NUPXFPQW.js";import{useWidgetSettings as n}from"./chunk-ZR72F7TE.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-JNL7A5HC.js";import"./chunk-D4HWQ3ET.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as l,useCallback as r,useEffect as i}from"react";import{jsxs as o,Fragment as a,jsx as c}from"react/jsx-runtime";var s="calc_appearance";function u(){const[u,d]=l("0"),[h,m]=l(null),[b,k]=l(null),[g,p]=l(!1),[x,N]=l(""),[v,y]=l([]),[f,C]=l(!1),[$,j]=l(()=>e(s)),[w,E]=l(!1),[L,T]=l($);n(r(()=>{T({...$}),E(!0)},[$]));const W=r(e=>{N(""),d(t=>g||"0"===t?(p(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[g]),B=r(()=>{d("0"),m(null),k(null),p(!1)},[]),F=r((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}},[]),S=r(e=>{const t=parseFloat(u);if(null!==h&&b&&!g){const e=F(h,t,b);d(String(e)),m(e),y(n=>[`${h} ${b} ${t} = ${e}`,...n].slice(0,20))}else m(t);k(e),p(!0)},[u,h,b,g,F]),P=r(()=>{if(null===h||!b)return;const e=parseFloat(u),t=F(h,e,b),n=`${h} ${b} ${e} =`;y(e=>[`${n} ${t}`,...e].slice(0,20)),N(n),d(String(t)),m(null),k(null),p(!0)},[u,h,b,F]),A=r(()=>{d(e=>String(parseFloat(e)/100))},[]),H=r(()=>{d(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"?W(e.key):"."===e.key?W("."):"+"===e.key?S("+"):"-"===e.key?S("-"):"*"===e.key?S("×"):"/"===e.key?(e.preventDefault(),S("÷")):"Enter"===e.key||"="===e.key?P():"Escape"===e.key?B():"Backspace"===e.key?d(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&A())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[W,S,P,B,A]);const I="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",J=`${I} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,M=`${I} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,D=`${I} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,R=`${I} bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800`;/* @__PURE__ */
2
2
  return o(a,{children:[
3
3
  /* @__PURE__ */o("div",{className:"flex flex-col h-full",style:{opacity:$.activeOpacity/100,backdropFilter:$.activeBlur>0?`blur(${$.activeBlur}px)`:void 0},children:[
4
4
  /* @__PURE__ */o("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__ */c("div",{className:"flex flex-col justify-end flex-1 overflow-hidden",children:y.slice(0,3).reverse().map((e,t)=>/* @__PURE__ */c("div",{className:"text-[11px] text-slate-400 text-right font-mono truncate",children:e},t))}),(x||b&&null!==h)&&/* @__PURE__ */c("div",{className:"text-base text-slate-600 text-right font-mono",children:x||`${h} ${b} ${g?"":u}`}),
5
+ /* @__PURE__ */c("div",{className:"flex flex-col justify-end flex-1 overflow-hidden",children:v.slice(0,3).reverse().map((e,t)=>/* @__PURE__ */c("div",{className:"text-[11px] text-slate-400 text-right font-mono truncate",children:e},t))}),(x||b&&null!==h)&&/* @__PURE__ */c("div",{className:"text-base text-slate-600 text-right font-mono",children:x||`${h} ${b} ${g?"":u}`}),
6
6
  /* @__PURE__ */o("div",{className:"flex items-center gap-2",children:[
7
7
  /* @__PURE__ */c("button",{onClick:()=>{navigator.clipboard.writeText(u),C(!0),setTimeout(()=>C(!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__ */c("svg",f?{className:"h-5 w-5 text-green-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("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__ */c("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
8
  /* @__PURE__ */c("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)})(u)})]})]}),
9
9
  /* @__PURE__ */o("div",{className:"grid grid-cols-4 grid-rows-5 gap-1.5 flex-1 min-h-0 p-2",children:[
10
- /* @__PURE__ */c("button",{onClick:B,className:V,children:"AC"}),
11
- /* @__PURE__ */c("button",{onClick:D,className:V,children:"+/−"}),
12
- /* @__PURE__ */c("button",{onClick:A,className:V,children:"%"}),
13
- /* @__PURE__ */c("button",{onClick:()=>W("÷"),className:`${H} ${"÷"===b?"ring-2 ring-blue-400":""}`,children:"÷"}),
14
- /* @__PURE__ */c("button",{onClick:()=>T("7"),className:P,children:"7"}),
15
- /* @__PURE__ */c("button",{onClick:()=>T("8"),className:P,children:"8"}),
16
- /* @__PURE__ */c("button",{onClick:()=>T("9"),className:P,children:"9"}),
17
- /* @__PURE__ */c("button",{onClick:()=>W("×"),className:`${H} ${"×"===b?"ring-2 ring-blue-400":""}`,children:"×"}),
18
- /* @__PURE__ */c("button",{onClick:()=>T("4"),className:P,children:"4"}),
19
- /* @__PURE__ */c("button",{onClick:()=>T("5"),className:P,children:"5"}),
20
- /* @__PURE__ */c("button",{onClick:()=>T("6"),className:P,children:"6"}),
21
- /* @__PURE__ */c("button",{onClick:()=>W("-"),className:`${H} ${"-"===b?"ring-2 ring-blue-400":""}`,children:"−"}),
22
- /* @__PURE__ */c("button",{onClick:()=>T("1"),className:P,children:"1"}),
23
- /* @__PURE__ */c("button",{onClick:()=>T("2"),className:P,children:"2"}),
24
- /* @__PURE__ */c("button",{onClick:()=>T("3"),className:P,children:"3"}),
25
- /* @__PURE__ */c("button",{onClick:()=>W("+"),className:`${H} ${"+"===b?"ring-2 ring-blue-400":""}`,children:"+"}),
26
- /* @__PURE__ */c("button",{onClick:()=>T("0"),className:`${P} col-span-2`,children:"0"}),
27
- /* @__PURE__ */c("button",{onClick:()=>T("."),className:P,children:"."}),
28
- /* @__PURE__ */c("button",{onClick:M,className:J,children:"="})]})]}),
29
- /* @__PURE__ */c(t,{open:w,onClose:()=>E(!1),title:"Calculator Settings",appearance:L,onAppearanceChange:S,onSave:()=>{j(L),localStorage.setItem(s,JSON.stringify(L)),E(!1)}})]})}export{u as default};
10
+ /* @__PURE__ */c("button",{onClick:B,className:D,children:"AC"}),
11
+ /* @__PURE__ */c("button",{onClick:H,className:D,children:"+/−"}),
12
+ /* @__PURE__ */c("button",{onClick:A,className:D,children:"%"}),
13
+ /* @__PURE__ */c("button",{onClick:()=>S("÷"),className:`${M} ${"÷"===b?"ring-2 ring-blue-400":""}`,children:"÷"}),
14
+ /* @__PURE__ */c("button",{onClick:()=>W("7"),className:J,children:"7"}),
15
+ /* @__PURE__ */c("button",{onClick:()=>W("8"),className:J,children:"8"}),
16
+ /* @__PURE__ */c("button",{onClick:()=>W("9"),className:J,children:"9"}),
17
+ /* @__PURE__ */c("button",{onClick:()=>S("×"),className:`${M} ${"×"===b?"ring-2 ring-blue-400":""}`,children:"×"}),
18
+ /* @__PURE__ */c("button",{onClick:()=>W("4"),className:J,children:"4"}),
19
+ /* @__PURE__ */c("button",{onClick:()=>W("5"),className:J,children:"5"}),
20
+ /* @__PURE__ */c("button",{onClick:()=>W("6"),className:J,children:"6"}),
21
+ /* @__PURE__ */c("button",{onClick:()=>S("-"),className:`${M} ${"-"===b?"ring-2 ring-blue-400":""}`,children:"−"}),
22
+ /* @__PURE__ */c("button",{onClick:()=>W("1"),className:J,children:"1"}),
23
+ /* @__PURE__ */c("button",{onClick:()=>W("2"),className:J,children:"2"}),
24
+ /* @__PURE__ */c("button",{onClick:()=>W("3"),className:J,children:"3"}),
25
+ /* @__PURE__ */c("button",{onClick:()=>S("+"),className:`${M} ${"+"===b?"ring-2 ring-blue-400":""}`,children:"+"}),
26
+ /* @__PURE__ */c("button",{onClick:()=>W("0"),className:`${J} col-span-2`,children:"0"}),
27
+ /* @__PURE__ */c("button",{onClick:()=>W("."),className:J,children:"."}),
28
+ /* @__PURE__ */c("button",{onClick:P,className:R,children:"="})]})]}),
29
+ /* @__PURE__ */c(t,{open:w,onClose:()=>E(!1),title:"Calculator Settings",appearance:L,onAppearanceChange:T,onSave:()=>{j(L),localStorage.setItem(s,JSON.stringify(L)),E(!1)}})]})}export{u as default};
@@ -1 +1 @@
1
- export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-LVFMK5OQ.js";import"./chunk-TR6PLN7W.js";
1
+ export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-D4HWQ3ET.js";import"./chunk-TR6PLN7W.js";
@@ -1,4 +1,4 @@
1
- import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-GDSGXDET.js";import{useWidgetSettings as r}from"./chunk-7DAQ3WVP.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-2RHMSFZV.js";import"./chunk-LVFMK5OQ.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as a,useCallback as n,useEffect as s}from"react";import{jsxs as c,Fragment as o,jsx as i}from"react/jsx-runtime";var l=["USD","CNY","AUD","GBP","EUR","JPY","CAD","THB","NZD","SGD","HKD","CHF","KRW","INR","MXN","BRL"],m=[["USD","CNY"],["USD","AUD"],["GBP","USD"],["USD","JPY"]],d="currency_pairs",u="currency_appearance",p="currency_rates_cache";function h(e){try{const t=JSON.parse(localStorage.getItem(p)||"{}")[e];if(t&&Date.now()-t.timestamp<36e5)return t.rates}catch{}return null}function g(e,t){try{const r=JSON.parse(localStorage.getItem(p)||"{}");r[e]={rates:t,timestamp:Date.now()},localStorage.setItem(p,JSON.stringify(r))}catch{}}function x(){try{const e=JSON.parse(localStorage.getItem(d)||"");if(Array.isArray(e)&&e.length)return e.slice(0,4)}catch{}return m}var y={USD:"🇺🇸",CNY:"🇨🇳",AUD:"🇦🇺",GBP:"🇬🇧",JPY:"🇯🇵",CAD:"🇨🇦",EUR:"🇪🇺",THB:"🇹🇭",NZD:"🇳🇿",SGD:"🇸🇬",HKD:"🇭🇰",CHF:"🇨🇭",KRW:"🇰🇷",INR:"🇮🇳",MXN:"🇲🇽",BRL:"🇧🇷"};function f(){const[m,p]=a(x),[f,N]=a(()=>e(u)),[b,v]=a({}),[S,D]=a(!1),[k,C]=a(!1),[j,U]=a([]),[B,I]=a(f),[J,P]=a("USD"),[A,L]=a("CNY");r(n(()=>{U([...m]),I({...f}),C(!0)},[m,f])),s(()=>{const e=[...new Set(m.map(([e])=>e))];let t=!0;return async function(){D(!0);const r={};for(const t of e){const e=h(t);if(e)r[t]=e;else try{const e=await fetch(`https://open.er-api.com/v6/latest/${t}`),a=await e.json();a.rates&&(r[t]=a.rates,g(t,a.rates))}catch{}}t&&(v(r),D(!1))}(),()=>{t=!1}},[m]);/* @__PURE__ */
1
+ import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-NUPXFPQW.js";import{useWidgetSettings as r}from"./chunk-ZR72F7TE.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import"./chunk-JNL7A5HC.js";import"./chunk-D4HWQ3ET.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as a,useCallback as n,useEffect as s}from"react";import{jsxs as c,Fragment as o,jsx as i}from"react/jsx-runtime";var l=["USD","CNY","AUD","GBP","EUR","JPY","CAD","THB","NZD","SGD","HKD","CHF","KRW","INR","MXN","BRL"],m=[["USD","CNY"],["USD","AUD"],["GBP","USD"],["USD","JPY"]],d="currency_pairs",u="currency_appearance",p="currency_rates_cache";function h(e){try{const t=JSON.parse(localStorage.getItem(p)||"{}")[e];if(t&&Date.now()-t.timestamp<36e5)return t.rates}catch{}return null}function g(e,t){try{const r=JSON.parse(localStorage.getItem(p)||"{}");r[e]={rates:t,timestamp:Date.now()},localStorage.setItem(p,JSON.stringify(r))}catch{}}function x(){try{const e=JSON.parse(localStorage.getItem(d)||"");if(Array.isArray(e)&&e.length)return e.slice(0,4)}catch{}return m}var y={USD:"🇺🇸",CNY:"🇨🇳",AUD:"🇦🇺",GBP:"🇬🇧",JPY:"🇯🇵",CAD:"🇨🇦",EUR:"🇪🇺",THB:"🇹🇭",NZD:"🇳🇿",SGD:"🇸🇬",HKD:"🇭🇰",CHF:"🇨🇭",KRW:"🇰🇷",INR:"🇮🇳",MXN:"🇲🇽",BRL:"🇧🇷"};function f(){const[m,p]=a(x),[f,N]=a(()=>e(u)),[b,v]=a({}),[S,D]=a(!1),[k,C]=a(!1),[j,U]=a([]),[J,B]=a(f),[I,P]=a("USD"),[A,H]=a("CNY");r(n(()=>{U([...m]),B({...f}),C(!0)},[m,f])),s(()=>{const e=[...new Set(m.map(([e])=>e))];let t=!0;return async function(){D(!0);const r={};for(const t of e){const e=h(t);if(e)r[t]=e;else try{const e=await fetch(`https://open.er-api.com/v6/latest/${t}`),a=await e.json();a.rates&&(r[t]=a.rates,g(t,a.rates))}catch{}}t&&(v(r),D(!1))}(),()=>{t=!1}},[m]);/* @__PURE__ */
2
2
  return c(o,{children:[
3
3
  /* @__PURE__ */i("div",{style:{backgroundColor:`rgb(var(--taskbar-bg-rgb, 243 244 246) / ${f.activeOpacity/100})`,backdropFilter:f.activeBlur>0?`blur(${f.activeBlur}px)`:void 0},children:/* @__PURE__ */c("div",{className:"px-4 py-3 space-y-1",children:[S&&/* @__PURE__ */i("div",{className:"text-xs text-gray-400 text-center py-4",children:"Loading rates..."}),m.map(([e,t],r)=>{const a=b[e]?.[t];/* @__PURE__ */
4
4
  return c("button",{onClick:()=>{const e=m.map((e,t)=>t===r?[e[1],e[0]]:e);p(e),localStorage.setItem(d,JSON.stringify(e))},className:"flex items-center justify-between px-2 py-2 border-b border-gray-200 last:border-0 w-full hover:bg-gray-100 rounded transition-colors cursor-pointer",children:[
@@ -9,13 +9,13 @@ return c("button",{onClick:()=>{const e=m.map((e,t)=>t===r?[e[1],e[0]]:e);p(e),l
9
9
  /* @__PURE__ */i("span",{className:"text-base",children:y[t]||""}),
10
10
  /* @__PURE__ */i("span",{className:"text-sm font-semibold text-gray-700",children:t})]}),
11
11
  /* @__PURE__ */i("div",{className:"text-base font-mono font-semibold text-gray-900 tabular-nums",children:null!=a?a.toLocaleString(void 0,{minimumFractionDigits:2,maximumFractionDigits:4}):"—"})]},`${e}-${t}-${r}`)})]})}),
12
- /* @__PURE__ */i(t,{open:k,onClose:()=>C(!1),title:"Currency Settings",appearance:B,onAppearanceChange:I,onSave:()=>{if(0===j.length)return;const e=j.slice(0,4);p(e),N(B),localStorage.setItem(d,JSON.stringify(e)),localStorage.setItem(u,JSON.stringify(B)),C(!1)},children:/* @__PURE__ */c("div",{children:[
12
+ /* @__PURE__ */i(t,{open:k,onClose:()=>C(!1),title:"Currency Settings",appearance:J,onAppearanceChange:B,onSave:()=>{if(0===j.length)return;const e=j.slice(0,4);p(e),N(J),localStorage.setItem(d,JSON.stringify(e)),localStorage.setItem(u,JSON.stringify(J)),C(!1)},children:/* @__PURE__ */c("div",{children:[
13
13
  /* @__PURE__ */c("h3",{className:"text-sm font-semibold text-gray-700 mb-2",children:["Currency Pairs ",
14
14
  /* @__PURE__ */c("span",{className:"text-[11px] font-normal text-gray-400",children:["(",j.length,"/",4,")"]})]}),
15
15
  /* @__PURE__ */i("div",{className:"space-y-1 mb-2",children:j.map(([e,t],r)=>/* @__PURE__ */c("div",{className:"flex items-center justify-between py-1 px-2 bg-gray-50 rounded",children:[
16
16
  /* @__PURE__ */c("span",{className:"text-sm",children:[y[e]||""," ",e," → ",y[t]||""," ",t]}),
17
17
  /* @__PURE__ */i("button",{onClick:()=>U(e=>e.filter((e,t)=>t!==r)),className:"text-red-400 hover:text-red-600",children:"×"})]},r))}),j.length<4?/* @__PURE__ */c("div",{className:"flex items-center gap-2",children:[
18
- /* @__PURE__ */i("select",{value:J,onChange:e=>P(e.target.value),className:"bg-gray-50 border border-gray-200 rounded px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500",children:l.map(e=>/* @__PURE__ */i("option",{children:e},e))}),
18
+ /* @__PURE__ */i("select",{value:I,onChange:e=>P(e.target.value),className:"bg-gray-50 border border-gray-200 rounded px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500",children:l.map(e=>/* @__PURE__ */i("option",{children:e},e))}),
19
19
  /* @__PURE__ */i("span",{className:"text-gray-400",children:"→"}),
20
- /* @__PURE__ */i("select",{value:A,onChange:e=>L(e.target.value),className:"bg-gray-50 border border-gray-200 rounded px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500",children:l.map(e=>/* @__PURE__ */i("option",{children:e},e))}),
21
- /* @__PURE__ */i("button",{onClick:()=>{J!==A&&j.length<4&&U(e=>[...e,[J,A]])},className:"text-sm font-medium text-blue-600 hover:text-blue-800 px-2",children:"+ Add"})]}):/* @__PURE__ */c("p",{className:"text-[11px] text-gray-400 italic",children:["Max ",4," pairs — remove one to add another."]})]})})]})}export{f as default};
20
+ /* @__PURE__ */i("select",{value:A,onChange:e=>H(e.target.value),className:"bg-gray-50 border border-gray-200 rounded px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500",children:l.map(e=>/* @__PURE__ */i("option",{children:e},e))}),
21
+ /* @__PURE__ */i("button",{onClick:()=>{I!==A&&j.length<4&&U(e=>[...e,[I,A]])},className:"text-sm font-medium text-blue-600 hover:text-blue-800 px-2",children:"+ Add"})]}):/* @__PURE__ */c("p",{className:"text-[11px] text-gray-400 italic",children:["Max ",4," pairs — remove one to add another."]})]})})]})}export{f as default};
@@ -1,8 +1,8 @@
1
- import{escapeHtml as e}from"./chunk-BR22X7E5.js";import{AboutApp as t}from"./chunk-RJ4LACFH.js";import{toast_default as n}from"./chunk-KKOHUQPF.js";import"./chunk-TWV42Q3K.js";import{WindowTitle as r}from"./chunk-7DAQ3WVP.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import{PopupMenu as o,PopupMenuLabel as l,PopupMenuItem as a,PopupMenuDivider as i}from"./chunk-2RHMSFZV.js";import"./chunk-LVFMK5OQ.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as s,useRef as c}from"react";import{jsxs as d,jsx as h}from"react/jsx-runtime";var m=/* @__PURE__ */new Set(["txt","md","markdown","csv","tsv","log","json","xml","html","htm","css","js","jsx","ts","tsx","py","rb","go","rs","java","c","h","cpp","hpp","sh","bash","yml","yaml","toml","ini","conf","env","sql"]),u=/* @__PURE__ */new Set(["docx"]),p={filename:"Untitled",kind:"docx",content:"",ext:"docx"};function g(){const[g,x]=s(p),[f,y]=s(!1),[v,b]=s(!1),[k,w]=s(!1),[N,C]=s(null),L=c(null),j=c(null),D=c(null),M=(e,t)=>{D.current?.focus(),document.execCommand(e,!1,t),w(!0)},U=e=>{for(const t of e){if(!t.type.startsWith("image/"))continue;const e=new FileReader;e.onload=()=>{D.current?.focus(),document.execCommand("insertImage",!1,String(e.result)),w(!0)},e.readAsDataURL(t)}},R=e=>{N&&(N.el.removeAttribute("width"),N.el.removeAttribute("height"),N.el.style.width=e??"",N.el.style.height=e?"auto":"",w(!0),C(null))},B=async t=>{const r=(t.name.split(".").pop()||"").toLowerCase();y(!0);try{if(m.has(r)||!u.has(r)&&t.type.startsWith("text/")){const n=await t.text(),o=e(n).replace(/\n/g,"<br>");x({filename:t.name,kind:"text",content:o,ext:r}),w(!1)}else if(u.has(r))try{const e=await(import(
1
+ import{escapeHtml as e}from"./chunk-BR22X7E5.js";import{AboutApp as t}from"./chunk-NV35RTZK.js";import{toast_default as n}from"./chunk-KKOHUQPF.js";import"./chunk-6JXLEPRE.js";import{WindowTitle as r}from"./chunk-ZR72F7TE.js";import"./chunk-V453E4KU.js";import"./chunk-UB4JIOLD.js";import"./chunk-PH3PRIFP.js";import{PopupMenu as o,PopupMenuLabel as l,PopupMenuItem as a,PopupMenuDivider as i}from"./chunk-JNL7A5HC.js";import"./chunk-D4HWQ3ET.js";import"./chunk-57MIENLJ.js";import"./chunk-MAIHBBWT.js";import"./chunk-TR6PLN7W.js";import"./chunk-D65T4H6J.js";import{useState as s,useRef as c}from"react";import{jsxs as d,jsx as h}from"react/jsx-runtime";var m=/* @__PURE__ */new Set(["txt","md","markdown","csv","tsv","log","json","xml","html","htm","css","js","jsx","ts","tsx","py","rb","go","rs","java","c","h","cpp","hpp","sh","bash","yml","yaml","toml","ini","conf","env","sql"]),u=/* @__PURE__ */new Set(["docx"]),p={filename:"Untitled",kind:"docx",content:"",ext:"docx"};function g(){const[g,x]=s(p),[f,y]=s(!1),[v,b]=s(!1),[k,w]=s(!1),[N,C]=s(null),L=c(null),j=c(null),D=c(null),M=(e,t)=>{D.current?.focus(),document.execCommand(e,!1,t),w(!0)},R=e=>{for(const t of e){if(!t.type.startsWith("image/"))continue;const e=new FileReader;e.onload=()=>{D.current?.focus(),document.execCommand("insertImage",!1,String(e.result)),w(!0)},e.readAsDataURL(t)}},U=e=>{N&&(N.el.removeAttribute("width"),N.el.removeAttribute("height"),N.el.style.width=e??"",N.el.style.height=e?"auto":"",w(!0),C(null))},B=async t=>{const r=(t.name.split(".").pop()||"").toLowerCase();y(!0);try{if(m.has(r)||!u.has(r)&&t.type.startsWith("text/")){const n=await t.text(),o=e(n).replace(/\n/g,"<br>");x({filename:t.name,kind:"text",content:o,ext:r}),w(!1)}else if(u.has(r))try{const e=await(import(
2
2
  /* @vite-ignore */
3
- "mammoth")),n=await t.arrayBuffer(),o=await e.convertToHtml({arrayBuffer:n});x({filename:t.name,kind:"docx",content:o.value||"<p><em>(empty document)</em></p>",ext:r}),w(!1)}catch(e){n.error('Install the optional "mammoth" peer dep to read .docx files.')}else"doc"===r?n.error(".doc is the legacy Word binary format — convert to .docx first."):n.error(`Unsupported file type: .${r||"unknown"}`)}finally{y(!1)}},W=g?.filename?(A=g.filename).length>24?`${A.slice(0,23)}…`:A:"Untitled";var A;/* @__PURE__ */
4
- return d("div",{className:"relative flex flex-col h-full",onDragOver:e=>{e.preventDefault(),v||b(!0)},onDragLeave:e=>{e.currentTarget===e.target&&b(!1)},onDrop:e=>{e.preventDefault(),b(!1);const t=Array.from(e.dataTransfer.files??[]);0!==t.length&&(t.every(e=>e.type.startsWith("image/"))?U(t):B(t[0]))},children:[
5
- /* @__PURE__ */h(r,{title:`${W}${k?" •":""} - Documents`}),
3
+ "mammoth")),n=await t.arrayBuffer(),o=await e.convertToHtml({arrayBuffer:n});x({filename:t.name,kind:"docx",content:o.value||"<p><em>(empty document)</em></p>",ext:r}),w(!1)}catch(e){n.error('Install the optional "mammoth" peer dep to read .docx files.')}else"doc"===r?n.error(".doc is the legacy Word binary format — convert to .docx first."):n.error(`Unsupported file type: .${r||"unknown"}`)}finally{y(!1)}},T=g?.filename?(W=g.filename).length>24?`${W.slice(0,23)}…`:W:"Untitled";var W;/* @__PURE__ */
4
+ return d("div",{className:"relative flex flex-col h-full",onDragOver:e=>{e.preventDefault(),v||b(!0)},onDragLeave:e=>{e.currentTarget===e.target&&b(!1)},onDrop:e=>{e.preventDefault(),b(!1);const t=Array.from(e.dataTransfer.files??[]);0!==t.length&&(t.every(e=>e.type.startsWith("image/"))?R(t):B(t[0]))},children:[
5
+ /* @__PURE__ */h(r,{title:`${T}${k?" •":""} - Documents`}),
6
6
  /* @__PURE__ */h(t,{app:"documents"}),
7
7
  /* @__PURE__ */d("div",{className:"flex items-center flex-wrap gap-x-2 gap-y-1 px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0",children:[
8
8
  /* @__PURE__ */h("input",{ref:L,type:"file",accept:".txt,.md,.csv,.tsv,.log,.json,.xml,.html,.htm,.css,.js,.jsx,.ts,.tsx,.py,.rb,.go,.rs,.java,.c,.h,.cpp,.hpp,.sh,.bash,.yml,.yaml,.toml,.ini,.conf,.env,.sql,.docx,text/*",onChange:e=>{const t=e.target.files?.[0];t&&B(t),L.current&&(L.current.value="")},className:"hidden"}),
@@ -38,15 +38,15 @@ return d("div",{className:"relative flex flex-col h-full",onDragOver:e=>{e.preve
38
38
  /* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("justifyRight"),className:"px-2 py-1 rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Align right",children:/* @__PURE__ */h("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */h("path",{strokeLinecap:"round",d:"M3.75 6h16.5M10.5 12h9.75M6 18h14.25"})})}),
39
39
  /* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("justifyFull"),className:"px-2 py-1 rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Justify",children:/* @__PURE__ */h("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */h("path",{strokeLinecap:"round",d:"M3.75 6h16.5M3.75 12h16.5M3.75 18h16.5"})})})]}),
40
40
  /* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
41
- /* @__PURE__ */h("input",{ref:j,type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:e=>{e.target.files?.length&&U(Array.from(e.target.files)),j.current&&(j.current.value="")}}),
41
+ /* @__PURE__ */h("input",{ref:j,type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:e=>{e.target.files?.length&&R(Array.from(e.target.files)),j.current&&(j.current.value="")}}),
42
42
  /* @__PURE__ */d("button",{onClick:()=>j.current?.click(),className:"px-2 py-1 text-xs rounded text-gray-700 hover:bg-gray-200 transition-colors flex items-center gap-1",title:"Insert image (or paste / drop one)",children:[
43
43
  /* @__PURE__ */h("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */h("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"})}),"Image"]})]}),
44
- /* @__PURE__ */h("div",{className:"flex-1 min-h-0 overflow-hidden",children:/* @__PURE__ */h("div",f?{className:"flex items-center justify-center h-full text-sm text-gray-400",children:"Loading…"}:{className:"h-full overflow-auto "+("docx"===g.kind?"bg-gray-100 px-6 py-8":"bg-white"),children:/* @__PURE__ */h("div",{ref:D,contentEditable:!0,suppressContentEditableWarning:!0,spellCheck:!1,onInput:()=>w(!0),onPaste:e=>{const t=Array.from(e.clipboardData?.items??[]).filter(e=>"file"===e.kind&&e.type.startsWith("image/")).map(e=>e.getAsFile()).filter(e=>!!e);t.length&&(e.preventDefault(),U(t))},onClick:e=>{const t=e.target;"IMG"===t.tagName&&(e.preventDefault(),C({x:e.clientX,y:e.clientY,el:t}))},dangerouslySetInnerHTML:{__html:g.content},className:"docx"===g.kind?"docs-editor mx-auto w-[8.5in] min-h-[11in] bg-white p-[1in] shadow text-[14px] leading-relaxed text-gray-800 outline-none focus:ring-2 focus:ring-blue-400/40":"docs-editor block w-full min-h-full p-4 font-mono text-[13px] leading-relaxed text-gray-800 bg-white outline-none whitespace-pre-wrap"})})}),v&&/* @__PURE__ */h("div",{className:"absolute inset-0 bg-blue-500/15 border-4 border-dashed border-blue-500 pointer-events-none flex items-center justify-center z-20",children:/* @__PURE__ */h("div",{className:"px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium shadow-lg",children:"Drop a document to open · images insert into the page"})}),N&&/* @__PURE__ */d(o,{minWidth:150,style:{left:N.x,top:N.y},onClose:()=>C(null),children:[
44
+ /* @__PURE__ */h("div",{className:"flex-1 min-h-0 overflow-hidden",children:/* @__PURE__ */h("div",f?{className:"flex items-center justify-center h-full text-sm text-gray-400",children:"Loading…"}:{className:"h-full overflow-auto "+("docx"===g.kind?"bg-gray-100 px-6 py-8":"bg-white"),children:/* @__PURE__ */h("div",{ref:D,contentEditable:!0,suppressContentEditableWarning:!0,spellCheck:!1,onInput:()=>w(!0),onPaste:e=>{const t=Array.from(e.clipboardData?.items??[]).filter(e=>"file"===e.kind&&e.type.startsWith("image/")).map(e=>e.getAsFile()).filter(e=>!!e);t.length&&(e.preventDefault(),R(t))},onClick:e=>{const t=e.target;"IMG"===t.tagName&&(e.preventDefault(),C({x:e.clientX,y:e.clientY,el:t}))},dangerouslySetInnerHTML:{__html:g.content},className:"docx"===g.kind?"docs-editor mx-auto w-[8.5in] min-h-[11in] bg-white p-[1in] shadow text-[14px] leading-relaxed text-gray-800 outline-none focus:ring-2 focus:ring-blue-400/40":"docs-editor block w-full min-h-full p-4 font-mono text-[13px] leading-relaxed text-gray-800 bg-white outline-none whitespace-pre-wrap"})})}),v&&/* @__PURE__ */h("div",{className:"absolute inset-0 bg-blue-500/15 border-4 border-dashed border-blue-500 pointer-events-none flex items-center justify-center z-20",children:/* @__PURE__ */h("div",{className:"px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium shadow-lg",children:"Drop a document to open · images insert into the page"})}),N&&/* @__PURE__ */d(o,{minWidth:150,style:{left:N.x,top:N.y},onClose:()=>C(null),children:[
45
45
  /* @__PURE__ */h(l,{children:"Image width"}),
46
- /* @__PURE__ */h(a,{onClick:()=>R("25%"),children:"25%"}),
47
- /* @__PURE__ */h(a,{onClick:()=>R("50%"),children:"50%"}),
48
- /* @__PURE__ */h(a,{onClick:()=>R("75%"),children:"75%"}),
49
- /* @__PURE__ */h(a,{onClick:()=>R("100%"),children:"100%"}),
50
- /* @__PURE__ */h(a,{onClick:()=>R(null),children:"Original size"}),
46
+ /* @__PURE__ */h(a,{onClick:()=>U("25%"),children:"25%"}),
47
+ /* @__PURE__ */h(a,{onClick:()=>U("50%"),children:"50%"}),
48
+ /* @__PURE__ */h(a,{onClick:()=>U("75%"),children:"75%"}),
49
+ /* @__PURE__ */h(a,{onClick:()=>U("100%"),children:"100%"}),
50
+ /* @__PURE__ */h(a,{onClick:()=>U(null),children:"Original size"}),
51
51
  /* @__PURE__ */h(i,{}),
52
52
  /* @__PURE__ */h(a,{danger:!0,onClick:()=>{N?.el.remove(),w(!0),C(null)},children:"Remove image"})]})]})}export{g as default};