efficient-shell 4.168.0 → 4.171.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.
- package/README.md +151 -1
- package/dist/{Browser-PZPREN6H.js → Browser-BW3EZ7B2.js} +14 -14
- package/dist/Calculator-VBK5NSMU.js +29 -0
- package/dist/ConfirmDialog-YRCG3W2T.js +1 -0
- package/dist/{CurrencyConverter-3BTIZ2LT.js → CurrencyConverter-IW6F7HW4.js} +6 -6
- package/dist/{Documents-YAOM3L47.js → Documents-VH3JXSSJ.js} +5 -5
- package/dist/{Files-2UHYDMLL.js → Files-R4ZA5MXU.js} +30 -30
- package/dist/{Notepad-OWL75AYX.js → Notepad-FOITSJJA.js} +10 -10
- package/dist/{PomodoroTimer-SCPEOG6W.js → PomodoroTimer-C4SVIFC6.js} +31 -31
- package/dist/{Preview-5R3QZSJU.js → Preview-5K6LK6WZ.js} +21 -21
- package/dist/{Sidebar-C5RXL72L.js → Sidebar-FDFNRXJU.js} +20 -20
- package/dist/Spreadsheet-CZC3QU2G.js +37 -0
- package/dist/{Stock-UGDIALNB.js → Stock-B4WWEBZH.js} +6 -6
- package/dist/{Weather-CR2MN5XF.js → Weather-TDB5AY23.js} +15 -15
- package/dist/{WorldClock-JBNJ7C7J.js → WorldClock-HYHDVPBV.js} +7 -7
- package/dist/apps/index.js +1 -1
- package/dist/bin/ui-check.js +1 -1
- package/dist/brand.css +1 -1
- package/dist/{chunk-JLPJBO7K.js → chunk-2UIKLYAI.js} +1 -1
- package/dist/{chunk-6MBERZOS.js → chunk-36QX6LOQ.js} +3 -3
- package/dist/{chunk-SOI4LR67.js → chunk-5G4QMZGJ.js} +3 -3
- package/dist/chunk-67ZUPDWG.js +1 -0
- package/dist/{chunk-PLX2N4N6.js → chunk-7YFAFXQG.js} +2 -2
- package/dist/{chunk-FVXBJGY5.js → chunk-AUKURHBZ.js} +3 -3
- package/dist/{chunk-A7Q4BCPI.js → chunk-CRI4UFBU.js} +5 -5
- package/dist/{chunk-M4DB7UBZ.js → chunk-ECFMRDUP.js} +1 -1
- package/dist/chunk-EXXHI5DO.js +12 -0
- package/dist/chunk-FWOPZB6I.js +1 -0
- package/dist/chunk-FWZUTHP5.js +112 -0
- package/dist/chunk-GKLJ2SYS.js +995 -0
- package/dist/{chunk-YWXYBJ5Y.js → chunk-HA2WG27U.js} +2 -2
- package/dist/{chunk-CUX4XGLS.js → chunk-HNXPIYRS.js} +1 -1
- package/dist/{chunk-QZG72OVX.js → chunk-NTCAZ6Y3.js} +1 -1
- package/dist/{chunk-N3ZXQE4M.js → chunk-PGVUO7GB.js} +5 -5
- package/dist/{chunk-XKHAP6N2.js → chunk-Y3UKUB7V.js} +8 -8
- package/dist/chunk-YKZHOXI4.js +2 -0
- package/dist/icons/efficient.d.ts +355 -0
- package/dist/icons/efficient.js +470 -0
- package/dist/icons/heroicons.d.ts +6 -0
- package/dist/icons/heroicons.js +1 -0
- package/dist/icons/index.d.ts +64 -0
- package/dist/icons/index.js +2 -0
- package/dist/icons/lucide.d.ts +6 -0
- package/dist/icons/lucide.js +1 -0
- package/dist/{index-CbLbd__n.d.ts → index-Dq20bi8D.d.ts} +125 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +650 -645
- package/dist/map/index.js +3 -3
- package/dist/page-tabs/index.js +5 -5
- package/dist/registry-FHdUeVww.d.ts +71 -0
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui.css +81 -0
- package/package.json +27 -1
- package/dist/Calculator-NXMUEH5D.js +0 -29
- package/dist/ConfirmDialog-ZDVMT74Y.js +0 -1
- package/dist/Spreadsheet-XT4HF7MQ.js +0 -37
- package/dist/chunk-7U3F53IG.js +0 -1
- package/dist/chunk-GVZLCY3B.js +0 -994
- package/dist/chunk-JYLI2WXW.js +0 -12
- package/dist/chunk-LW27IM3S.js +0 -112
package/README.md
CHANGED
|
@@ -965,6 +965,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
|
|
|
965
965
|
| `<ShellAuthProvider value={{ hasAnyPerm }}>` | Permission-filter nav items. |
|
|
966
966
|
| `<ShellPrefsProvider value={{ prefs, save }}>` | Where the shell reads/writes user prefs (theme, taskbar pos, sticky notes, …). Use `useLocalStoragePrefs(key)` for a backend-less default. Since 4.92.0 it is also how `<EntityList>` / `<ResizableTable>` column config and sort persist: with no provider mounted, `useShellPrefs()` reads empty and drops saves, so both silently degrade to localStorage-only and never reach the user's profile. Session restore reads `session_windows` once, at mount: hand the provider prefs that are already loaded by then (an adapter whose prefs arrive later misses that load's replay, though the saved set is kept). |
|
|
967
967
|
| `<ShellStringsProvider value={{ … }} locale?>` | Translates every word the shell and the kit draw on their own account — window controls, taskbar hints, dialogs, pickers, pagers, list footers, upload zones, charts, timelines. English works with NO provider; the override is a typed partial merged per section, so an incomplete catalog falls back rather than breaking. Prop-level text (`emptyText`, placeholders) always wins over the catalog. `locale` (a BCP 47 tag) writes dates and numbers that locale's way; without one nothing moves. See [Languages, dates and numbers](#languages-dates-and-numbers--shellstringsprovider) for the full catalog. |
|
|
968
|
+
| `<ShellLanguageProvider languages language strings? onChange? reload?>` | Which interface language is in force. Takes the tag `resolveShellLanguage` chose before mount and that language's shell catalog, mounts `ShellStringsProvider` with both, stamps `<html lang>`, and gives `useShellLanguage()` its `setLanguage`, which saves the choice and reloads. See [Choosing the language](#choosing-the-language--shelllanguageprovider). |
|
|
968
969
|
| `<ShellEntityFetcherProvider value={(endpoint, id) => …}>` | How the modal stack fetches entity data. |
|
|
969
970
|
| `<BugReportConfigProvider value={{ submit, list?, resolve? }}>` | Wire the bug-report flow to your backend. |
|
|
970
971
|
| `<DesktopHostProvider value={{ stickyResolver?, saveShortcuts?, … }}>` | Sticky-note ref resolver + persistence callbacks. |
|
|
@@ -995,6 +996,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
|
|
|
995
996
|
| `useUndoCanEdit(canEdit)` | A form's own word on whether the record may be edited right now — `useUndoCanEdit(!isLocked)`. While false the stack records nothing, ⌘Z is left alone and the footer shows no controls. A nested `<UndoProvider canEdit={false}>` in the form's JSX says the same thing: it shadows the stack for its children AND forwards the read-only claim to the window's stack, which is where the form's own `useUndoableState` calls (made above it in the tree) register. Either form of the claim makes the whole window read-only. The positive claim, `useUndoCanEdit(true)`, is how a window that edits in place outside Edit mode — a detail with inline cells behind a permission — asks the footer for the pair. |
|
|
996
997
|
| `useMultiModal()` | Manages multi-window stacking + activate/blur. |
|
|
997
998
|
| `useShellAuth() / useShellPrefs() / useShellEntityFetcher() / useBugReport() / useDesktopHost()` | Context readers — the shell uses these internally; consumers may also call them. |
|
|
999
|
+
| `useShellLanguage()` | `{ language, languages, setLanguage }` — the active language's tag, the ones on offer, and the switch. English with nothing to switch to when no `ShellLanguageProvider` is mounted. |
|
|
998
1000
|
| `useShellStrings() / useShellLocale()` | The active catalog, and the provider's `locale` (`undefined` without one) — for a host cell that should write a date or a number the way the kit does. |
|
|
999
1001
|
|
|
1000
1002
|
### Apps barrel — `efficient-shell/apps`
|
|
@@ -1475,6 +1477,35 @@ classes in `ui.css` (the timeline card's) carry pixel radii of their own.
|
|
|
1475
1477
|
}
|
|
1476
1478
|
```
|
|
1477
1479
|
|
|
1480
|
+
**Corners.** A component does not pick a step of the scale for itself; it asks
|
|
1481
|
+
for the radius of what it is. Four role tokens, each defaulting to the step that
|
|
1482
|
+
role has always drawn, so they change nothing until you set one:
|
|
1483
|
+
|
|
1484
|
+
| Token | Default | Drawn by |
|
|
1485
|
+
|---|---|---|
|
|
1486
|
+
| `--radius-control` | `--radius-md` (6px) | buttons, fields, a segmented control's options |
|
|
1487
|
+
| `--radius-card` | `--radius-lg` (8px) | `Card`, `Dialog`, a segmented control's track |
|
|
1488
|
+
| `--radius-popup` | `--radius-2xl` (16px) | menus, select lists, the start menu, the search palette |
|
|
1489
|
+
| `--radius-window` | `--radius-2xl` (16px) | windows and their title bars |
|
|
1490
|
+
|
|
1491
|
+
They are plain custom properties: `:root { --radius-control: 2px; }` restyles
|
|
1492
|
+
one role and leaves the rest. Pills (switches, status badges, avatars) are round
|
|
1493
|
+
at every setting. Popovers, tooltips, drawers and menu rows still sit on their
|
|
1494
|
+
own scale steps, because each draws a different radius today and moving them
|
|
1495
|
+
onto a role would change how they look.
|
|
1496
|
+
|
|
1497
|
+
**Corners is also a setting of the theme.** The `corners` preference
|
|
1498
|
+
(`'square' | 'soft' | 'round'`, in Customization beside the colour theme) is
|
|
1499
|
+
stamped on `<html>` as `data-corners` by `useTheme` and
|
|
1500
|
+
`applyThemePrefs({ corners })`; a host with its own switcher calls
|
|
1501
|
+
`applyCorners(value)`. It rescales the whole radius scale, so the roles follow
|
|
1502
|
+
it and so does every scale utility in your own markup, and it remaps bare
|
|
1503
|
+
`rounded`, which the scale cannot reach. `soft` is the absence of the attribute:
|
|
1504
|
+
no rule applies and your own `@theme` radii still decide. `square` and `round`
|
|
1505
|
+
are a person's own choice, so they win over the host's theme, the way a chosen
|
|
1506
|
+
colour theme does. Do not write literal radii (an arbitrary-value radius class,
|
|
1507
|
+
an inline `borderRadius`): they are the one thing the setting cannot reach.
|
|
1508
|
+
|
|
1478
1509
|
**Glass.** Menus, popups, listboxes and tooltips are frosted glass
|
|
1479
1510
|
(`glassStyle()`). `--menu-opacity` (0–1, default `0.95`) sets how much shows
|
|
1480
1511
|
through. `rosh-reduce-transparency` on `<html>` makes every popup one solid
|
|
@@ -1595,6 +1626,62 @@ the field, because what is typed there is parsed back.
|
|
|
1595
1626
|
`formatDate(value, { locale, style })` or `fmtSliderDate(ms, locale)`, or hand it
|
|
1596
1627
|
to `Intl` directly — so a host's dates and numbers read like the kit's.
|
|
1597
1628
|
|
|
1629
|
+
#### Choosing the language — `ShellLanguageProvider`
|
|
1630
|
+
|
|
1631
|
+
`ShellStringsProvider` can speak another language; `ShellLanguageProvider` is
|
|
1632
|
+
what decides which. It holds the languages you offer, the one in force and the
|
|
1633
|
+
reader's saved choice, stamps `<html lang>`, and mounts `ShellStringsProvider`
|
|
1634
|
+
for you with that language's catalog and locale.
|
|
1635
|
+
|
|
1636
|
+
A language is fixed for the life of a page. Resolve it before you mount, load
|
|
1637
|
+
its copy, and hand both over; `setLanguage` saves the choice and reloads. That
|
|
1638
|
+
is deliberate: column sets, navigation and status buckets usually read their
|
|
1639
|
+
copy when they are imported, a list snapshots its columns when it mounts, and
|
|
1640
|
+
a reload is the one switch that leaves none of them in the old language.
|
|
1641
|
+
|
|
1642
|
+
```tsx
|
|
1643
|
+
import {
|
|
1644
|
+
ENGLISH, ShellLanguageProvider, resolveShellLanguage, useShellLanguage,
|
|
1645
|
+
type ShellLanguage,
|
|
1646
|
+
} from 'efficient-shell/ui';
|
|
1647
|
+
|
|
1648
|
+
const LANGUAGES: ShellLanguage[] = [ENGLISH, { tag: 'zh-Hans', name: '简体中文' }];
|
|
1649
|
+
|
|
1650
|
+
// Before React mounts: the saved choice, then the browser's list, then the first offered.
|
|
1651
|
+
const language = resolveShellLanguage({ offered: LANGUAGES });
|
|
1652
|
+
|
|
1653
|
+
<ShellLanguageProvider
|
|
1654
|
+
languages={LANGUAGES}
|
|
1655
|
+
language={language}
|
|
1656
|
+
strings={shellCatalogForThatLanguage} // omit for English
|
|
1657
|
+
onChange={tag => saveToTheAccount(tag)} // awaited, then the page reloads
|
|
1658
|
+
>
|
|
1659
|
+
<App />
|
|
1660
|
+
</ShellLanguageProvider>
|
|
1661
|
+
|
|
1662
|
+
const { language, languages, setLanguage } = useShellLanguage();
|
|
1663
|
+
```
|
|
1664
|
+
|
|
1665
|
+
- **Resolution.** `resolveShellLanguage` reads the choice saved on the device
|
|
1666
|
+
(`SHELL_LANGUAGE_STORAGE_KEY`, `react-os-shell:language`), then
|
|
1667
|
+
`navigator.languages`, then falls back to the first language offered. A
|
|
1668
|
+
browser asking for `zh-CN` or `zh-SG` gets `zh-Hans`; with both Chineses on
|
|
1669
|
+
offer `zh-TW` gets `zh-Hant`, and with only Simplified it gets that rather
|
|
1670
|
+
than English. A saved choice that is no longer offered is skipped.
|
|
1671
|
+
`matchShellLanguage(wanted, offered)` is the matching on its own.
|
|
1672
|
+
- **English keeps its dates and numbers.** A language's `locale` defaults to
|
|
1673
|
+
its tag. `ENGLISH` carries `locale: null`, so mounting the provider for
|
|
1674
|
+
English moves no date and no number: the kit writes them as it does with no
|
|
1675
|
+
provider at all.
|
|
1676
|
+
- **The account.** `onChange` is where a host with accounts keeps the choice.
|
|
1677
|
+
It is awaited before the reload, and a failure does not stop the switch: the
|
|
1678
|
+
device has the choice. `saveShellLanguage(tag)` returns `true` only when the
|
|
1679
|
+
write reads back, for a sign-in sync that would otherwise reload on a write
|
|
1680
|
+
that never landed.
|
|
1681
|
+
- **`reload={false}`** leaves the switch to you: the choice is saved and
|
|
1682
|
+
`onChange` runs, and you re-render the provider with the new `language` and
|
|
1683
|
+
`strings`.
|
|
1684
|
+
|
|
1598
1685
|
**What is not in the catalog, on purpose:** month and weekday names (the
|
|
1599
1686
|
`locale` supplies them); file-format names in `BrandAssetEditor`'s default
|
|
1600
1687
|
`acceptHint` and the `20ft`/`40ft` container codes (notation, not language); the
|
|
@@ -2581,6 +2668,68 @@ missing or cannot be read. All of them are also exported from
|
|
|
2581
2668
|
| `dismissPopups()`, `OVERLAY_OPEN_EVENT` | An overlay calls `dismissPopups()` as it opens; every open kit popup (`Select`, `SearchableSelect`, `TagInput`, `DatePicker`, `DateRangePicker`, `PopupMenu` via its `onClose`, `ServerStatusIndicator`) closes rather than floating over the overlay. The kit's own overlays already call it. A consumer's own popup listens for `OVERLAY_OPEN_EVENT` on `window` while open. |
|
|
2582
2669
|
| `Kbd` constants — `MOD`, `ALT`, `SHIFT`, `ENTER`, `ALT_SHIFT_E`, `CMD_K`, … | Symbol constants for rendering keyboard shortcuts. |
|
|
2583
2670
|
|
|
2671
|
+
### Icons — `efficient-shell/icons`
|
|
2672
|
+
|
|
2673
|
+
Every icon comes through this package (harness UI-24). A component asks for an
|
|
2674
|
+
icon by what it **means**, and the set the theme chose draws it:
|
|
2675
|
+
|
|
2676
|
+
```tsx
|
|
2677
|
+
import { Icon, registerIconSet } from 'efficient-shell/icons';
|
|
2678
|
+
import { heroicons } from 'efficient-shell/icons/heroicons';
|
|
2679
|
+
|
|
2680
|
+
registerIconSet(heroicons); // once, at startup, in client code
|
|
2681
|
+
|
|
2682
|
+
<Icon name="trash" /> // 1em square, the text's colour
|
|
2683
|
+
<Icon name="search" size={20} tone="muted" />
|
|
2684
|
+
<Icon name="warning" title="Overdue" /> // named: an image, not decoration
|
|
2685
|
+
```
|
|
2686
|
+
|
|
2687
|
+
`Icon` and the registry are also exported from `efficient-shell/ui` and the
|
|
2688
|
+
root entry. They import React and nothing else.
|
|
2689
|
+
|
|
2690
|
+
**The catalogue.** `IconName` is 197 meanings (`add`, `close`, `edit`, `trash`,
|
|
2691
|
+
`search`, `download`, `chevron-down`, `warning`, …), built from the icons the
|
|
2692
|
+
EFFICIENT frontends import today. `<Icon name>` is typed to it, so a misspelt
|
|
2693
|
+
meaning does not compile. To add one, add it to `src/icons/catalogue.json` with
|
|
2694
|
+
its icon in every package and run `npm run icons`.
|
|
2695
|
+
|
|
2696
|
+
**The sets.** Each is its own subpath, so a host bundles only what it
|
|
2697
|
+
registers, and the icon package behind it is an optional peer:
|
|
2698
|
+
|
|
2699
|
+
| Import | Set | Draws | Needs |
|
|
2700
|
+
|---|---|---|---|
|
|
2701
|
+
| `efficient-shell/icons/heroicons` | `heroicons` | the whole catalogue | `@heroicons/react` |
|
|
2702
|
+
| `efficient-shell/icons/lucide` | `lucide` | the whole catalogue | `lucide-react` (0.577 or later) |
|
|
2703
|
+
| `efficient-shell/icons/efficient` | `efficient` | the 165 house glyphs, which draw 58 of the catalogue meanings | nothing |
|
|
2704
|
+
|
|
2705
|
+
The first set registered is the default (`setDefaultIconSet(name)` changes
|
|
2706
|
+
that). A meaning the chosen set does not draw falls back to the default set, so
|
|
2707
|
+
a partial set never leaves a hole.
|
|
2708
|
+
|
|
2709
|
+
**Part of the theme.** The `icon_set` preference sits beside the colour theme
|
|
2710
|
+
and the corners: `useTheme` and `applyThemePrefs({ icon_set })` choose the set
|
|
2711
|
+
and stamp `data-icon-set` on `<html>`, and every `<Icon>` on the page redraws.
|
|
2712
|
+
A host with its own switcher calls `applyIconSet(name)` or `setIconSet(name)`;
|
|
2713
|
+
`iconSets()` lists what is registered. Like `corners`, a call without the key
|
|
2714
|
+
leaves the choice alone.
|
|
2715
|
+
|
|
2716
|
+
**A product's own glyphs.** An editor's block types and settings rows are not
|
|
2717
|
+
in the catalogue. Register them and draw them by `glyph`, with no icon package
|
|
2718
|
+
imported:
|
|
2719
|
+
|
|
2720
|
+
```tsx
|
|
2721
|
+
registerIcons('editor', { 'block-product': BlockProductGlyph });
|
|
2722
|
+
<Icon glyph="block-product" />
|
|
2723
|
+
```
|
|
2724
|
+
|
|
2725
|
+
They are found under any theme. `efficient-shell/icons/efficient` also exports
|
|
2726
|
+
each house glyph as a component (`TrashIcon`, `StylesIcon`, `PaddingTopIcon`,
|
|
2727
|
+
…, `size` 18 by default) for code that wants one drawing whatever the theme.
|
|
2728
|
+
|
|
2729
|
+
With no set registered, `<Icon>` draws nothing and warns once per meaning. The
|
|
2730
|
+
kit's own components (a window's close button, a filter chip) keep drawing
|
|
2731
|
+
through a built-in fallback, so a host that registers nothing sees no change.
|
|
2732
|
+
|
|
2584
2733
|
### The UI kit check — `efficient-shell-ui-check`
|
|
2585
2734
|
|
|
2586
2735
|
Every surface a person operates takes its UI from this package (harness
|
|
@@ -2616,8 +2765,9 @@ itself where the kit has an answer:
|
|
|
2616
2765
|
| `native` | `window.confirm` / `alert` / `prompt`, or a bare call nothing in the file binds | `confirm`, `confirmDestructive`, `prompt`, `toast` |
|
|
2617
2766
|
| `dark` | a `dark:` variant in a class string | the light class alone; the kit remaps it |
|
|
2618
2767
|
| `hex` | a hex colour in a `.tsx` string (not in `href`, `to`, `id`, `key`, `htmlFor`) | a token or a palette class |
|
|
2768
|
+
| `radius` | a literal corner radius: an arbitrary-value radius class (`rounded-[4px]`) or an inline `borderRadius` number or length (not `inherit`, `var(…)`, `50%` or `9999`) | a scale utility or a role token; the theme's Corners setting shapes them |
|
|
2619
2769
|
| `kit` | an import of a second UI kit (`@headlessui`, `@radix-ui`, `@mui`, `antd`, `sonner`, …) | the kit's component |
|
|
2620
|
-
| `icon` | an import of an icon package (`@heroicons`, `lucide-react`, `@tabler/icons`, …) |
|
|
2770
|
+
| `icon` | an import of an icon package (`@heroicons`, `lucide-react`, `@tabler/icons`, …) | `<Icon name>` from `efficient-shell/icons` |
|
|
2621
2771
|
| `kit-dep` | one of those packages declared in `package.json` (not `devDependencies`) | remove it |
|
|
2622
2772
|
|
|
2623
2773
|
Known gaps: `rgb()` / `hsl()` colours, colours in `.ts` maps, and
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-
|
|
1
|
+
import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-36QX6LOQ.js";import{WindowTitle as r}from"./chunk-FWZUTHP5.js";import"./chunk-DSSLOQDW.js";import"./chunk-6KO2U66R.js";import"./chunk-67ZUPDWG.js";import"./chunk-CRI4UFBU.js";import"./chunk-5A7MWTXX.js";import"./chunk-EXXHI5DO.js";import"./chunk-PGVUO7GB.js";import"./chunk-HZZNJHRH.js";import"./chunk-D65T4H6J.js";import{confirm as n}from"./chunk-ECFMRDUP.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-NCQLGQYR.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),[W,H]=s(0),[R,S]=s(f),[B,D]=s(!1),[O,U]=s(null),A=a(null),E=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(R))}catch{}},[R]);const P=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),D(!1))},T=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},F=()=>{const e=O?.trim();e?(S(t=>[...t,{label:e,url:k}]),U(null)):U(null)};i(()=>{if(null===O)return;A.current?.focus(),A.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||U(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==O]);const I=e=>{S(t=>t.filter((t,o)=>o!==e))},X=z>0,G=z<j.length-1,Q=R.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(j[e]),L(j[e]),
|
|
7
|
-
/* @__PURE__ */c("button",{onClick:()=>{if(z<j.length-1){const e=z+1;M(e),w(j[e]),L(j[e]),
|
|
8
|
-
/* @__PURE__ */c("button",{onClick:()=>
|
|
9
|
-
/* @__PURE__ */c("button",{onClick:()=>
|
|
10
|
-
/* @__PURE__ */c("form",{onSubmit:e=>{e.preventDefault(),
|
|
6
|
+
/* @__PURE__ */c("button",{onClick:()=>{if(z>0){const e=z-1;M(e),w(j[e]),L(j[e]),D(!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]),D(!1)}},disabled:!G,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:()=>H(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:()=>P(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(),P(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:()=>
|
|
14
|
-
/* @__PURE__ */c("button",{onClick:
|
|
15
|
-
/* @__PURE__ */c("button",{onClick:()=>
|
|
13
|
+
/* @__PURE__ */c("button",{"data-bookmark-popover":!0,onClick:()=>Q?I(R.findIndex(e=>e.url===k)):void U(v(k)),className:V+" "+(Q?"text-yellow-500":""),title:Q?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:Q?"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:T,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:()=>D(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:
|
|
18
|
+
/* @__PURE__ */c("input",{ref:A,type:"text",value:O,onChange:e=>U(e.target.value),onKeyDown:e=>{"Enter"===e.key?F():"Escape"===e.key&&U(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:()=>
|
|
21
|
-
/* @__PURE__ */c("button",{onClick:
|
|
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:()=>
|
|
20
|
+
/* @__PURE__ */c("button",{onClick:()=>U(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:!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:()=>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"})&&I(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:
|
|
26
|
+
/* @__PURE__ */c("div",{className:"flex-1 relative min-h-0 bg-gray-50",children:/* @__PURE__ */c(y,{url:k,iframeKey:W,iframeRef:E,openExternal:T,showHelp:B,dismissHelp:()=>D(!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-2UIKLYAI.js";import{useWidgetSettings as n}from"./chunk-FWZUTHP5.js";import"./chunk-DSSLOQDW.js";import"./chunk-6KO2U66R.js";import"./chunk-CRI4UFBU.js";import"./chunk-5A7MWTXX.js";import"./chunk-EXXHI5DO.js";import"./chunk-PGVUO7GB.js";import"./chunk-HZZNJHRH.js";import"./chunk-D65T4H6J.js";import"./chunk-ECFMRDUP.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-NCQLGQYR.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)),[E,L]=r(!1),[F,S]=r(j),T=l(null);n(o(()=>{S({...j}),L(!0)},[j]));const H=o(e=>{y(""),h(t=>g||"0"===t?(v(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[g]),O=o(()=>{h("0"),k(null),p(null),v(!1)},[]),U=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=U(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,U]),A=o(()=>{if(null===m||!b)return;const e=parseFloat(d),t=U(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,U]),B=o(()=>{h(e=>String(parseFloat(e)/100))},[]),D=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"?H(e.key):"."===e.key?H("."):"+"===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(),A()):"Escape"===e.key?O():"Backspace"===e.key?h(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&B())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[H,W,A,O,B]);const I="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",X=`${I} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,P=`${I} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,R=`${I} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,M=`${I} 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:O,className:R,children:"AC"}),
|
|
11
|
+
/* @__PURE__ */s("button",{onClick:D,className:R,children:"+/−"}),
|
|
12
|
+
/* @__PURE__ */s("button",{onClick:B,className:R,children:"%"}),
|
|
13
|
+
/* @__PURE__ */s("button",{onClick:()=>W("÷"),className:`${P} ${"÷"===b?"ring-2 ring-blue-400":""}`,children:"÷"}),
|
|
14
|
+
/* @__PURE__ */s("button",{onClick:()=>H("7"),className:X,children:"7"}),
|
|
15
|
+
/* @__PURE__ */s("button",{onClick:()=>H("8"),className:X,children:"8"}),
|
|
16
|
+
/* @__PURE__ */s("button",{onClick:()=>H("9"),className:X,children:"9"}),
|
|
17
|
+
/* @__PURE__ */s("button",{onClick:()=>W("×"),className:`${P} ${"×"===b?"ring-2 ring-blue-400":""}`,children:"×"}),
|
|
18
|
+
/* @__PURE__ */s("button",{onClick:()=>H("4"),className:X,children:"4"}),
|
|
19
|
+
/* @__PURE__ */s("button",{onClick:()=>H("5"),className:X,children:"5"}),
|
|
20
|
+
/* @__PURE__ */s("button",{onClick:()=>H("6"),className:X,children:"6"}),
|
|
21
|
+
/* @__PURE__ */s("button",{onClick:()=>W("-"),className:`${P} ${"-"===b?"ring-2 ring-blue-400":""}`,children:"−"}),
|
|
22
|
+
/* @__PURE__ */s("button",{onClick:()=>H("1"),className:X,children:"1"}),
|
|
23
|
+
/* @__PURE__ */s("button",{onClick:()=>H("2"),className:X,children:"2"}),
|
|
24
|
+
/* @__PURE__ */s("button",{onClick:()=>H("3"),className:X,children:"3"}),
|
|
25
|
+
/* @__PURE__ */s("button",{onClick:()=>W("+"),className:`${P} ${"+"===b?"ring-2 ring-blue-400":""}`,children:"+"}),
|
|
26
|
+
/* @__PURE__ */s("button",{onClick:()=>H("0"),className:`${X} col-span-2`,children:"0"}),
|
|
27
|
+
/* @__PURE__ */s("button",{onClick:()=>H("."),className:X,children:"."}),
|
|
28
|
+
/* @__PURE__ */s("button",{onClick:A,className:M,children:"="})]})]}),
|
|
29
|
+
/* @__PURE__ */s(t,{open:E,onClose:()=>L(!1),title:"Calculator Settings",appearance:F,onAppearanceChange:S,onSave:()=>{w(F),localStorage.setItem(u,JSON.stringify(F)),L(!1)}})]})}export{d as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-ECFMRDUP.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-NCQLGQYR.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-
|
|
1
|
+
import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-2UIKLYAI.js";import{useWidgetSettings as r}from"./chunk-FWZUTHP5.js";import"./chunk-DSSLOQDW.js";import"./chunk-6KO2U66R.js";import"./chunk-CRI4UFBU.js";import"./chunk-5A7MWTXX.js";import"./chunk-EXXHI5DO.js";import"./chunk-PGVUO7GB.js";import"./chunk-HZZNJHRH.js";import"./chunk-D65T4H6J.js";import"./chunk-ECFMRDUP.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-NCQLGQYR.js";import"./chunk-YKZHOXI4.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"]],u="currency_pairs",p="currency_appearance",d="currency_rates_cache";function h(e){try{const t=JSON.parse(localStorage.getItem(d)||"{}")[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(d)||"{}");r[e]={rates:t,timestamp:Date.now()},localStorage.setItem(d,JSON.stringify(r))}catch{}}function x(){try{const e=JSON.parse(localStorage.getItem(u)||"");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,d]=a(x),[f,N]=a(()=>e(p)),[b,v]=a({}),[S,D]=a(!1),[k,C]=a(!1),[j,U]=a([]),[I,O]=a(f),[H,J]=a("USD"),[R,A]=a("CNY");r(n(()=>{U([...m]),O({...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);d(e),localStorage.setItem(u,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);d(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:
|
|
12
|
+
/* @__PURE__ */i(t,{open:k,onClose:()=>C(!1),title:"Currency Settings",appearance:I,onAppearanceChange:O,onSave:()=>{if(0===j.length)return;const e=j.slice(0,4);d(e),N(I),localStorage.setItem(u,JSON.stringify(e)),localStorage.setItem(p,JSON.stringify(I)),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
|
-
/* @__PURE__ */i("button",{onClick:()=>
|
|
18
|
-
/* @__PURE__ */i("select",{value:
|
|
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:H,onChange:e=>J(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:
|
|
21
|
-
/* @__PURE__ */i("button",{onClick:()=>{
|
|
20
|
+
/* @__PURE__ */i("select",{value:R,onChange:e=>A(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:()=>{H!==R&&j.length<4&&U(e=>[...e,[H,R]])},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,11 +1,11 @@
|
|
|
1
|
-
import{escapeHtml as e}from"./chunk-BR22X7E5.js";import{AboutApp as t}from"./chunk-
|
|
1
|
+
import{escapeHtml as e}from"./chunk-BR22X7E5.js";import{AboutApp as t}from"./chunk-36QX6LOQ.js";import{WindowTitle as n}from"./chunk-FWZUTHP5.js";import"./chunk-DSSLOQDW.js";import"./chunk-6KO2U66R.js";import"./chunk-67ZUPDWG.js";import{toast_default as r}from"./chunk-KSSAVLO7.js";import"./chunk-CRI4UFBU.js";import"./chunk-5A7MWTXX.js";import"./chunk-EXXHI5DO.js";import{PopupMenu as o,PopupMenuLabel as l,PopupMenuItem as a,PopupMenuDivider as i}from"./chunk-PGVUO7GB.js";import"./chunk-HZZNJHRH.js";import"./chunk-D65T4H6J.js";import"./chunk-ECFMRDUP.js";import"./chunk-AFYQTVZO.js";import"./chunk-X4FJ54PP.js";import"./chunk-NCQLGQYR.js";import"./chunk-YKZHOXI4.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),j=c(null),D=c(null),L=c(null),M=(e,t)=>{L.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=()=>{L.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))},O=async t=>{const n=(t.name.split(".").pop()||"").toLowerCase();y(!0);try{if(m.has(n)||!u.has(n)&&t.type.startsWith("text/")){const r=await t.text(),o=e(r).replace(/\n/g,"<br>");x({filename:t.name,kind:"text",content:o,ext:n}),w(!1)}else if(u.has(n))try{const e=await(import(
|
|
2
2
|
/* @vite-ignore */
|
|
3
|
-
"mammoth")),
|
|
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):
|
|
5
|
-
/* @__PURE__ */h(
|
|
3
|
+
"mammoth")),r=await t.arrayBuffer(),o=await e.convertToHtml({arrayBuffer:r});x({filename:t.name,kind:"docx",content:o.value||"<p><em>(empty document)</em></p>",ext:n}),w(!1)}catch(e){r.error('Install the optional "mammoth" peer dep to read .docx files.')}else"doc"===n?r.error(".doc is the legacy Word binary format — convert to .docx first."):r.error(`Unsupported file type: .${n||"unknown"}`)}finally{y(!1)}},B=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/"))?U(t):O(t[0]))},children:[
|
|
5
|
+
/* @__PURE__ */h(n,{title:`${B}${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
|
-
/* @__PURE__ */h("input",{ref:j,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&&
|
|
8
|
+
/* @__PURE__ */h("input",{ref:j,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&&O(t),j.current&&(j.current.value="")},className:"hidden"}),
|
|
9
9
|
/* @__PURE__ */d("button",{onClick:()=>j.current?.click(),className:"text-xs text-gray-700 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors flex items-center gap-1",children:[
|
|
10
10
|
/* @__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:"M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 00-1.883 2.542l.857 6a2.25 2.25 0 002.227 1.932H19.05a2.25 2.25 0 002.227-1.932l.857-6a2.25 2.25 0 00-1.883-2.542m-16.5 0V6A2.25 2.25 0 016 3.75h3.879a1.5 1.5 0 011.06.44l2.122 2.12a1.5 1.5 0 001.06.44H18A2.25 2.25 0 0120.25 9v.776"})}),"Open"]}),
|
|
11
11
|
/* @__PURE__ */h("button",{onClick:()=>{if(!g)return;const t=L.current?.innerHTML??"";if("text"===g.kind){if(/<(b|strong|i|em|u|font|span style|ul|ol|img)|style="[^"]*text-align/i.test(t)){const n=new Blob([`<!doctype html><meta charset="utf-8"><title>${e(g.filename)}</title><body style="font-family:ui-monospace,monospace;white-space:pre-wrap">${t}`],{type:"text/html"}),r=URL.createObjectURL(n),o=document.createElement("a");o.href=r,o.download=`${g.filename.replace(/\.[^.]+$/,"")}.html`,o.click(),URL.revokeObjectURL(r)}else{const e=L.current?.innerText??"",t=new Blob([e],{type:"text/plain"}),n=URL.createObjectURL(t),r=document.createElement("a");r.href=n,r.download=g.filename,r.click(),URL.revokeObjectURL(n)}}else{const n=new Blob([`<!doctype html><meta charset="utf-8"><title>${e(g.filename)}</title>${t}`],{type:"text/html"}),r=URL.createObjectURL(n),o=document.createElement("a");o.href=r,o.download=`${g.filename.replace(/\.docx$/i,"")}.html`,o.click(),URL.revokeObjectURL(r)}},className:"text-xs text-gray-700 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors",children:"Save"}),
|