efficient-shell 4.134.0 → 4.137.1
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/LICENSE +6 -17
- package/README.md +84 -8
- package/dist/Browser-ZX5OTOKK.js +43 -0
- package/dist/Calculator-4SQGOQFQ.js +29 -0
- package/dist/ConfirmDialog-NPKW2XHM.js +1 -0
- package/dist/CurrencyConverter-2KOM7L6V.js +21 -0
- package/dist/Documents-IZTIQYPG.js +52 -0
- package/dist/Files-B63KKXGZ.js +89 -0
- package/dist/Notepad-WA77V45J.js +25 -0
- package/dist/PdfViewer-RBRGEKWF.js +1 -0
- package/dist/PomodoroTimer-SDUBKXUS.js +99 -0
- package/dist/Preview-D4KOA4OI.js +187 -0
- package/dist/Sidebar-Y57LYXXI.js +23 -0
- package/dist/Spreadsheet-JX5E6WH6.js +37 -0
- package/dist/Stock-XAQ5WMUZ.js +16 -0
- package/dist/Weather-HLAGJ5LV.js +60 -0
- package/dist/WorldClock-IRI4VCTA.js +32 -0
- package/dist/apps/index.js +1 -151
- package/dist/brand.css +1 -1
- package/dist/chunk-3A46NCXK.js +29 -0
- package/dist/chunk-44UO7FYU.js +11 -0
- package/dist/chunk-466CM2TJ.js +1 -0
- package/dist/chunk-57MIENLJ.js +1 -0
- package/dist/chunk-5CRAF2AD.js +2 -0
- package/dist/chunk-A2OQLLYK.js +6 -0
- package/dist/chunk-B43AGQET.js +4 -0
- package/dist/chunk-BR22X7E5.js +1 -0
- package/dist/chunk-BUTSU7FO.js +1 -0
- package/dist/chunk-D65T4H6J.js +1 -0
- package/dist/chunk-ESL5TDNA.js +1 -0
- package/dist/chunk-FBDZGO3V.js +1 -0
- package/dist/chunk-FHTLC7HH.js +1 -0
- package/dist/chunk-FQLMX3IE.js +948 -0
- package/dist/chunk-H562R4GX.js +34 -0
- package/dist/chunk-JN4WXTWJ.js +106 -0
- package/dist/chunk-LVDRBRYU.js +1 -0
- package/dist/chunk-LWLCNQY7.js +1 -0
- package/dist/chunk-MAIHBBWT.js +1 -0
- package/dist/chunk-NPJH5MD7.js +13 -0
- package/dist/chunk-OCSOMMY2.js +1 -0
- package/dist/chunk-OQDWLHZI.js +1 -0
- package/dist/chunk-OWSAMA3I.js +23 -0
- package/dist/chunk-PH3PRIFP.js +5 -0
- package/dist/chunk-TAWKWSPN.js +9 -0
- package/dist/chunk-U4GTZPXP.js +1 -0
- package/dist/chunk-UB4JIOLD.js +2 -0
- package/dist/chunk-UZAJ5BF6.js +9 -0
- package/dist/chunk-VEGMDXT4.js +1 -0
- package/dist/chunk-VTVSMRFX.js +1 -0
- package/dist/chunk-VVAGSKW7.js +1 -0
- package/dist/chunk-XO43FJRM.js +19 -0
- package/dist/chunk-Y7BOLDRM.js +69 -0
- package/dist/file-intake/index.js +1 -4
- package/dist/{index-DZ7E7bCl.d.ts → index-DVI9DMSu.d.ts} +189 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +639 -7473
- package/dist/map/index.js +20 -540
- package/dist/markdown/index.js +6 -184
- package/dist/markup/index.js +1 -135
- package/dist/page-tabs/index.js +21 -709
- package/dist/sounds-OMHXVVQ4.js +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -19
- package/dist/ui.css +78 -10
- package/package.json +4 -3
- package/dist/Browser-O3QZGUF2.js +0 -482
- package/dist/Browser-O3QZGUF2.js.map +0 -1
- package/dist/Calculator-L6N5X3KU.js +0 -192
- package/dist/Calculator-L6N5X3KU.js.map +0 -1
- package/dist/ConfirmDialog-LYSSZSUD.js +0 -4
- package/dist/ConfirmDialog-LYSSZSUD.js.map +0 -1
- package/dist/CurrencyConverter-64MKXB3D.js +0 -236
- package/dist/CurrencyConverter-64MKXB3D.js.map +0 -1
- package/dist/Documents-5WXXYCLI.js +0 -441
- package/dist/Documents-5WXXYCLI.js.map +0 -1
- package/dist/Files-AUURUUDN.js +0 -805
- package/dist/Files-AUURUUDN.js.map +0 -1
- package/dist/Notepad-GPXJVPB7.js +0 -410
- package/dist/Notepad-GPXJVPB7.js.map +0 -1
- package/dist/PdfViewer-HKO6P4SR.js +0 -5
- package/dist/PdfViewer-HKO6P4SR.js.map +0 -1
- package/dist/PomodoroTimer-4TQBWLP2.js +0 -633
- package/dist/PomodoroTimer-4TQBWLP2.js.map +0 -1
- package/dist/Preview-FOZYPKM2.js +0 -2959
- package/dist/Preview-FOZYPKM2.js.map +0 -1
- package/dist/Sidebar-BPU7RCZP.js +0 -291
- package/dist/Sidebar-BPU7RCZP.js.map +0 -1
- package/dist/Spreadsheet-3C66BBBF.js +0 -519
- package/dist/Spreadsheet-3C66BBBF.js.map +0 -1
- package/dist/Stock-IF4IHYLU.js +0 -158
- package/dist/Stock-IF4IHYLU.js.map +0 -1
- package/dist/Weather-725PFR7T.js +0 -431
- package/dist/Weather-725PFR7T.js.map +0 -1
- package/dist/WorldClock-UU4NZIQ7.js +0 -202
- package/dist/WorldClock-UU4NZIQ7.js.map +0 -1
- package/dist/apps/index.js.map +0 -1
- package/dist/chunk-2TPTHAKI.js +0 -316
- package/dist/chunk-2TPTHAKI.js.map +0 -1
- package/dist/chunk-4P44JXDS.js +0 -195
- package/dist/chunk-4P44JXDS.js.map +0 -1
- package/dist/chunk-5O42JXQE.js +0 -26
- package/dist/chunk-5O42JXQE.js.map +0 -1
- package/dist/chunk-72CQWN7O.js +0 -547
- package/dist/chunk-72CQWN7O.js.map +0 -1
- package/dist/chunk-7CCHEEYC.js +0 -94
- package/dist/chunk-7CCHEEYC.js.map +0 -1
- package/dist/chunk-BE7FZOFU.js +0 -17
- package/dist/chunk-BE7FZOFU.js.map +0 -1
- package/dist/chunk-D276EMXS.js +0 -57
- package/dist/chunk-D276EMXS.js.map +0 -1
- package/dist/chunk-D7PYW2QS.js +0 -265
- package/dist/chunk-D7PYW2QS.js.map +0 -1
- package/dist/chunk-DVZWYWSD.js +0 -26
- package/dist/chunk-DVZWYWSD.js.map +0 -1
- package/dist/chunk-ET6ID4LP.js +0 -102
- package/dist/chunk-ET6ID4LP.js.map +0 -1
- package/dist/chunk-GA35NEND.js +0 -56
- package/dist/chunk-GA35NEND.js.map +0 -1
- package/dist/chunk-GIGV2ZRW.js +0 -70
- package/dist/chunk-GIGV2ZRW.js.map +0 -1
- package/dist/chunk-IPXN646P.js +0 -14
- package/dist/chunk-IPXN646P.js.map +0 -1
- package/dist/chunk-IRWSRJ4K.js +0 -48
- package/dist/chunk-IRWSRJ4K.js.map +0 -1
- package/dist/chunk-IULP5BCD.js +0 -79
- package/dist/chunk-IULP5BCD.js.map +0 -1
- package/dist/chunk-MGGY74RY.js +0 -14
- package/dist/chunk-MGGY74RY.js.map +0 -1
- package/dist/chunk-OLJDJYSU.js +0 -13678
- package/dist/chunk-OLJDJYSU.js.map +0 -1
- package/dist/chunk-PIGDNN5F.js +0 -46
- package/dist/chunk-PIGDNN5F.js.map +0 -1
- package/dist/chunk-Q2MJVSJT.js +0 -7
- package/dist/chunk-Q2MJVSJT.js.map +0 -1
- package/dist/chunk-Q3LT745N.js +0 -3710
- package/dist/chunk-Q3LT745N.js.map +0 -1
- package/dist/chunk-QAGQRNKI.js +0 -145
- package/dist/chunk-QAGQRNKI.js.map +0 -1
- package/dist/chunk-QRL64J5F.js +0 -503
- package/dist/chunk-QRL64J5F.js.map +0 -1
- package/dist/chunk-QSKCQUZE.js +0 -1103
- package/dist/chunk-QSKCQUZE.js.map +0 -1
- package/dist/chunk-R4OQIQYX.js +0 -153
- package/dist/chunk-R4OQIQYX.js.map +0 -1
- package/dist/chunk-RT6DSB5Y.js +0 -143
- package/dist/chunk-RT6DSB5Y.js.map +0 -1
- package/dist/chunk-SHQM5CK3.js +0 -549
- package/dist/chunk-SHQM5CK3.js.map +0 -1
- package/dist/chunk-T4VQHMG4.js +0 -822
- package/dist/chunk-T4VQHMG4.js.map +0 -1
- package/dist/chunk-TRCWINHF.js +0 -105
- package/dist/chunk-TRCWINHF.js.map +0 -1
- package/dist/chunk-TW7LPMVR.js +0 -16
- package/dist/chunk-TW7LPMVR.js.map +0 -1
- package/dist/chunk-W622KQTD.js +0 -465
- package/dist/chunk-W622KQTD.js.map +0 -1
- package/dist/chunk-X4Q6G253.js +0 -416
- package/dist/chunk-X4Q6G253.js.map +0 -1
- package/dist/chunk-YNKK7NE3.js +0 -171
- package/dist/chunk-YNKK7NE3.js.map +0 -1
- package/dist/chunk-YPO6RDMX.js +0 -20
- package/dist/chunk-YPO6RDMX.js.map +0 -1
- package/dist/file-intake/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/map/index.js.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/markup/index.js.map +0 -1
- package/dist/page-tabs/index.js.map +0 -1
- package/dist/sounds-NT4DEZGD.js +0 -3
- package/dist/sounds-NT4DEZGD.js.map +0 -1
- package/dist/ui/index.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
Copyright (c) 2026 Efficient Pty Ltd. All rights reserved.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
3
|
+
This software and its documentation are proprietary to Efficient Pty Ltd and
|
|
4
|
+
are confidential. No licence is granted to use, copy, modify, merge, publish,
|
|
5
|
+
distribute, sublicense or sell this software, in whole or in part, except
|
|
6
|
+
under a written agreement with Efficient Pty Ltd.
|
|
14
7
|
|
|
15
8
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
9
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
10
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
package/README.md
CHANGED
|
@@ -313,6 +313,72 @@ for the same copy path and toast.
|
|
|
313
313
|
Note that a cross-origin iframe is outside the reach of any parent listener —
|
|
314
314
|
the page inside it shows whatever menu it draws for itself.
|
|
315
315
|
|
|
316
|
+
### Dropdown menus
|
|
317
|
+
|
|
318
|
+
`DropdownMenu` is a button and the menu it opens, drawn with `PopupMenu` so it
|
|
319
|
+
looks like every other menu in the app.
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import { DropdownMenu } from 'efficient-shell/ui';
|
|
323
|
+
import Link from 'next/link';
|
|
324
|
+
|
|
325
|
+
<DropdownMenu
|
|
326
|
+
trigger={<>Leads <ChevronDown aria-hidden /></>}
|
|
327
|
+
triggerClassName={onLeadsPage ? 'nav-link underline' : 'nav-link'}
|
|
328
|
+
align="start"
|
|
329
|
+
linkAs={Link}
|
|
330
|
+
minWidth="16rem"
|
|
331
|
+
items={[
|
|
332
|
+
{ key: 'list', label: 'Leads list', href: '/leads', current: path === '/leads' },
|
|
333
|
+
{ key: 'days', label: 'Day planner', href: '/leads/days' },
|
|
334
|
+
{ key: 'd1', type: 'divider' },
|
|
335
|
+
{ key: 'theme', type: 'label', label: 'Theme' },
|
|
336
|
+
{ key: 'light', type: 'radio', label: 'Light', checked: theme === 'light', onSelect: () => setTheme('light') },
|
|
337
|
+
{ key: 'dark', type: 'radio', label: 'Dark', checked: theme === 'dark', onSelect: () => setTheme('dark') },
|
|
338
|
+
{ key: 'd2', type: 'divider' },
|
|
339
|
+
{ key: 'out', label: 'Sign out', onSelect: signOut },
|
|
340
|
+
]}
|
|
341
|
+
/>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Where it opens.** Right under its trigger, 4px below it. With `align="start"`
|
|
345
|
+
the menu's left edge is on the trigger's left edge. With `align="end"`, the
|
|
346
|
+
default, its right edge is on the trigger's right edge. `side="top"` opens it
|
|
347
|
+
above instead. When there is no room on that side it opens on the other, and
|
|
348
|
+
near an edge it moves along rather than run off. Inside a shell window it stays
|
|
349
|
+
inside the window (UI-11). The menu is portalled to `<body>` on the popup layer
|
|
350
|
+
(`Z_LAYERS.popup`) and follows its trigger when the page scrolls or the window
|
|
351
|
+
is dragged. The side it ended up on is on the surface as `data-side`.
|
|
352
|
+
|
|
353
|
+
**Entries.** Every entry has a `key`:
|
|
354
|
+
|
|
355
|
+
| Entry | Shape | Drawn as |
|
|
356
|
+
|---|---|---|
|
|
357
|
+
| Action | `{ key, label, onSelect, icon?, danger?, disabled? }` | `<button role="menuitem">`. Every item written before the other kinds existed is one. |
|
|
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
|
+
| 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
|
+
| Label | `{ key, type: 'label', label }` | A heading (`PopupMenuLabel`). Not focusable. |
|
|
361
|
+
| Divider | `{ key, type: 'divider' }` | `role="separator"` (`PopupMenuDivider`). |
|
|
362
|
+
|
|
363
|
+
**Props beyond `trigger`, `items`, `align` and `side`.** `linkAs` draws each
|
|
364
|
+
link with your router's link component (Next's `Link`) in place of `<a>`. It
|
|
365
|
+
receives `href`, `role`, `tabIndex`, `aria-current`, `className`, `style`,
|
|
366
|
+
`onClick`, `onMouseEnter` and the label. `triggerClassName` replaces the
|
|
367
|
+
trigger button's own classes, so it can look like your nav link or your button.
|
|
368
|
+
It stays a `<button aria-haspopup="menu" aria-expanded>`, named by its content
|
|
369
|
+
unless you pass `aria-label`. `menuClassName` is added to the menu's surface,
|
|
370
|
+
and `minWidth` (pixels, or any CSS length; 180 by default) sets its narrowest.
|
|
371
|
+
|
|
372
|
+
**Keyboard** (the WAI-ARIA menu button). Enter, Space or ArrowDown on the
|
|
373
|
+
trigger opens the menu on its first entry, and ArrowUp opens it on its last.
|
|
374
|
+
Inside the menu, the arrows move between the entries that can be chosen,
|
|
375
|
+
skipping labels, dividers and disabled entries, and wrap at the ends. Home and
|
|
376
|
+
End jump to the first and the last. A letter moves to the next entry starting
|
|
377
|
+
with it, and letters typed together search for the whole run. Enter or Space
|
|
378
|
+
chooses; on a link Enter follows it, and so does Space. Escape closes the menu
|
|
379
|
+
and gives focus back to the trigger, and so does Tab. A click elsewhere closes
|
|
380
|
+
it and leaves focus where you clicked.
|
|
381
|
+
|
|
316
382
|
## API reference
|
|
317
383
|
|
|
318
384
|
All exports are named — `import { Modal, ... } from 'efficient-shell'`.
|
|
@@ -333,7 +399,7 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
|
|
|
333
399
|
| `Modal`, `ModalActions`, `CopyButton`, `CancelButton` | Window primitive supporting standard / compact / widget styles. |
|
|
334
400
|
| `PopupMenu`, `PopupMenuItem`, `PopupMenuDivider`, `PopupMenuLabel`, `PopupSubmenu` | Right-click / context-menu primitive; `PopupSubmenu` is a row that opens a nested menu. |
|
|
335
401
|
| `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). |
|
|
336
|
-
| `DropdownMenu` |
|
|
402
|
+
| `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). |
|
|
337
403
|
| `ConfirmProvider`, `confirm` | Imperative `confirm({ title, body })` returning a Promise<boolean>. |
|
|
338
404
|
| `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`). |
|
|
339
405
|
| `ShortcutHelp` | The keyboard cheatsheet shown on `?`. |
|
|
@@ -355,18 +421,18 @@ All exports are named — `import { Modal, ... } from 'efficient-shell'`.
|
|
|
355
421
|
| `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. |
|
|
356
422
|
| `FormErrorSummary` | The error list at the top of a failed form (WCAG 3.3.1, the GOV.UK pattern): takes focus when errors appear, each message is a link that focuses the offending control by its `FormField` id. Renders nothing while `errors` is empty. |
|
|
357
423
|
| `TagInput` | Multi-value field — chosen values as removable chips, typing filters the option list in the same dropdown SearchableSelect uses. `allowFreeText` admits unlisted entries; Backspace in the empty input removes the last chip. The value array stays duplicate-free by construction. |
|
|
358
|
-
| `DatePicker`, `TimePicker`, `DateTimePicker`, `DateRangePicker` | Date/time fields
|
|
424
|
+
| `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` marks the trigger `aria-required` and drops Clear from the footer (`clearable` overrides either way); 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 `aria-required` and, unless `clearable` is given, removes Clear. Both pickers take `weekStartsOn` (0 Sunday, 1 Monday); without it the week starts where the provider's `locale` says. |
|
|
359
425
|
| `Card`, `StatCard` | Surface panel (optional header/footer) + dashboard metric tile. |
|
|
360
426
|
| `Avatar`, `AvatarGroup` | User avatar with initials fallback + status dot; overlapping stack with +N overflow. |
|
|
361
427
|
| `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. |
|
|
362
|
-
| `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)
|
|
428
|
+
| `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. |
|
|
363
429
|
| `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. |
|
|
364
430
|
| `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. `stackOnNarrow` turns each row into a labelled card on a narrow container — see [DataTable on a narrow screen](#datatable-on-a-narrow-screen). |
|
|
365
431
|
| `Pagination` | Numbered page control (pairs with tables; complements `ListFooter`). |
|
|
366
432
|
| `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. |
|
|
367
433
|
| `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. |
|
|
368
434
|
| `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. |
|
|
369
|
-
| `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`. |
|
|
435
|
+
| `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. |
|
|
370
436
|
| `DashboardTemplate`, `DataTablePage`, `FormLayoutPage`, `CheckoutTemplate`, `EmailTemplate`, `ChatTemplate`, `GalleryTemplate`, `AuthScreen`, `ErrorPage` | Zero-prop starter page templates composed from the primitives. |
|
|
371
437
|
| `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. |
|
|
372
438
|
| `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. |
|
|
@@ -828,6 +894,13 @@ word order a concatenation cannot express.
|
|
|
828
894
|
and the full date each day is announced as — from `Intl.DateTimeFormat` in
|
|
829
895
|
that locale (`Oktober`, `Mo.`, `2026年10月2日`). The calendar is always
|
|
830
896
|
Gregorian, whatever the locale's default.
|
|
897
|
+
- They also take the first day of the week from it: Monday for `en-AU`,
|
|
898
|
+
`en-GB` and `de`, Sunday for `en-US` and `ja` (`firstDayOfWeek(locale)`,
|
|
899
|
+
from the runtime's `Intl.Locale` week data). A bare `en` is `en-US`, so a
|
|
900
|
+
host serving Australians says `en-AU`. A runtime without the week data
|
|
901
|
+
(Firefox) and a Saturday-first locale get Sunday. A server render, and the
|
|
902
|
+
hydration pass after it, draw Sunday-first; the locale's week arrives in the
|
|
903
|
+
render after, because the server's week data and the reader's may differ.
|
|
831
904
|
- `DatePicker native`, `DateTimePicker` and `TimePicker` are drawn by the
|
|
832
905
|
browser, so they get the locale the one way they can: a `lang` attribute.
|
|
833
906
|
- `formatDate`, and the timelines' dates, are written by `Intl` in the locale
|
|
@@ -842,8 +915,8 @@ nothing changes: the same English month names, `DD/MM/YYYY` from the stored
|
|
|
842
915
|
setting, `toLocaleString()` with no argument, `String(v)`. Mounting the provider
|
|
843
916
|
for its strings alone moves no digit. A nested provider without a `locale`
|
|
844
917
|
keeps its parent's; a malformed tag (`en_US`) is reported once on the console
|
|
845
|
-
and ignored rather than thrown in render.
|
|
846
|
-
|
|
918
|
+
and ignored rather than thrown in render. A `weekStartsOn` prop still wins over
|
|
919
|
+
the locale's first day of the week. `InputNumber` keeps a `.` decimal in
|
|
847
920
|
the field, because what is typed there is parsed back.
|
|
848
921
|
|
|
849
922
|
`useShellLocale()` reads the tag for your own cells — pass it on as
|
|
@@ -1060,7 +1133,7 @@ with sample arguments.
|
|
|
1060
1133
|
|
|
1061
1134
|
</details>
|
|
1062
1135
|
|
|
1063
|
-
<details><summary><code>dateRange</code> —
|
|
1136
|
+
<details><summary><code>dateRange</code> — 19 keys</summary>
|
|
1064
1137
|
|
|
1065
1138
|
| Key | Type | English default |
|
|
1066
1139
|
|---|---|---|
|
|
@@ -1073,6 +1146,7 @@ with sample arguments.
|
|
|
1073
1146
|
| `end` | `string` | `End` |
|
|
1074
1147
|
| `fromOnly` | `(date: string) => string` | `From {date}` |
|
|
1075
1148
|
| `toOnly` | `(date: string) => string` | `To {date}` |
|
|
1149
|
+
| `range` | `(from: string, to: string) => string` | `{from} to {to}` |
|
|
1076
1150
|
| `last2Weeks` | `string` | `Last 2 Weeks` |
|
|
1077
1151
|
| `lastMonth` | `string` | `Last Month` |
|
|
1078
1152
|
| `last3Months` | `string` | `Last 3 Months` |
|
|
@@ -1788,4 +1862,6 @@ Typecheck runs twice on purpose: `tsconfig.json` is the *build* config, so `root
|
|
|
1788
1862
|
|
|
1789
1863
|
## License
|
|
1790
1864
|
|
|
1791
|
-
|
|
1865
|
+
Proprietary. Copyright (c) 2026 Efficient Pty Ltd. All rights reserved; see
|
|
1866
|
+
[LICENSE](./LICENSE). Versions published before the switch were released under
|
|
1867
|
+
the MIT License and stay under it.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import{peekBrowserStartUrl as e,claimBrowserStartUrl as t}from"./chunk-LWLCNQY7.js";import{AboutApp as o}from"./chunk-TAWKWSPN.js";import{WindowTitle as r}from"./chunk-JN4WXTWJ.js";import"./chunk-UB4JIOLD.js";import"./chunk-U4GTZPXP.js";import"./chunk-44UO7FYU.js";import"./chunk-PH3PRIFP.js";import"./chunk-UZAJ5BF6.js";import{confirm as n}from"./chunk-3A46NCXK.js";import"./chunk-57MIENLJ.js";import"./chunk-OQDWLHZI.js";import"./chunk-MAIHBBWT.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,B]=l(0),[H,S]=l(f),[A,R]=l(!1),[E,I]=l(null),P=a(null),T=a(null);i(()=>{try{localStorage.setItem(d,JSON.stringify(H))}catch{}},[H]);const U=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),R(!1))},D=()=>{"undefined"!=typeof window&&window.open(k,"_blank","noopener,noreferrer")},O=()=>{const e=E?.trim();e?(S(t=>[...t,{label:e,url:k}]),I(null)):I(null)};i(()=>{if(null===E)return;P.current?.focus(),P.current?.select();const e=e=>{const t=e.target;t?.closest("[data-bookmark-popover]")||I(null)},t=setTimeout(()=>document.addEventListener("mousedown",e),0);return()=>{clearTimeout(t),document.removeEventListener("mousedown",e)}},[null!==E]);const J=e=>{S(t=>t.filter((t,o)=>o!==e))},F=z>0,q=z<C.length-1,K=H.some(e=>e.url===k),V="p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";/* @__PURE__ */
|
|
2
|
+
return s("div",{className:"relative flex flex-col h-full bg-white",children:[
|
|
3
|
+
/* @__PURE__ */c(r,{title:`Browser - ${v(k)}`}),
|
|
4
|
+
/* @__PURE__ */c(o,{app:"browser"}),
|
|
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]),R(!1)}},disabled:!F,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<C.length-1){const e=z+1;M(e),w(C[e]),L(C[e]),R(!1)}},disabled:!q,className:V,title:"Forward",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M8.25 4.5l7.5 7.5-7.5 7.5"})})}),
|
|
8
|
+
/* @__PURE__ */c("button",{onClick:()=>B(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:()=>U(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(),U(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
|
+
/* @__PURE__ */c("span",{className:"px-2 text-gray-400 text-xs",children:k.startsWith("https://")?"🔒":"⚠️"}),
|
|
12
|
+
/* @__PURE__ */c("input",{type:"text",value:N,onChange:e=>L(e.target.value),onFocus:e=>e.target.select(),className:"flex-1 px-1 py-1 text-sm bg-transparent outline-none font-mono",spellCheck:!1,placeholder:"Enter URL or search…"}),k!==N&&/* @__PURE__ */c("button",{type:"button",onClick:()=>L(k),className:"px-1.5 text-[10px] text-gray-400 hover:text-gray-700",title:"Reset to current URL",children:"×"})]})}),
|
|
13
|
+
/* @__PURE__ */c("button",{"data-bookmark-popover":!0,onClick:()=>K?J(H.findIndex(e=>e.url===k)):void I(v(k)),className:V+" "+(K?"text-yellow-500":""),title:K?"Remove bookmark":"Add bookmark",children:/* @__PURE__ */c("svg",{className:"h-4 w-4",fill:K?"currentColor":"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */c("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"})})}),
|
|
14
|
+
/* @__PURE__ */c("button",{onClick:D,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:()=>R(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!==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:[
|
|
16
|
+
/* @__PURE__ */c("div",{className:"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1",children:"Bookmark this page"}),
|
|
17
|
+
/* @__PURE__ */c("div",{className:"text-[11px] text-gray-400 truncate mb-2 font-mono",title:k,children:k}),
|
|
18
|
+
/* @__PURE__ */c("input",{ref:P,type:"text",value:E,onChange:e=>I(e.target.value),onKeyDown:e=>{"Enter"===e.key?O():"Escape"===e.key&&I(null)},placeholder:"Name",className:"w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-200"}),
|
|
19
|
+
/* @__PURE__ */s("div",{className:"flex justify-end gap-1 mt-2",children:[
|
|
20
|
+
/* @__PURE__ */c("button",{onClick:()=>I(null),className:"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded",children:"Cancel"}),
|
|
21
|
+
/* @__PURE__ */c("button",{onClick:O,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:()=>U(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"})&&J(t)},className:"flex items-center gap-1.5 px-2 py-0.5 rounded text-[12px] text-gray-700 hover:bg-gray-100 whitespace-nowrap",title:`${e.url}\n(right-click to remove)`,children:[
|
|
23
|
+
/* @__PURE__ */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
|
+
/* @__PURE__ */c("div",{className:"flex-1"}),
|
|
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:T,openExternal:D,showHelp:A,dismissHelp:()=>R(!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
|
+
/* @__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
|
+
/* @__PURE__ */s("h3",{className:"text-base font-semibold text-gray-800 mb-1",children:[v(e)," can't be embedded"]}),
|
|
29
|
+
/* @__PURE__ */s("p",{className:"text-sm text-gray-500 mb-4",children:["This site sends an ",
|
|
30
|
+
/* @__PURE__ */c("span",{className:"font-mono text-xs",children:"X-Frame-Options"})," ","or ",
|
|
31
|
+
/* @__PURE__ */c("span",{className:"font-mono text-xs",children:"Content-Security-Policy"})," header that refuses iframe embedding. The browser blocks the load before our app can do anything about it."]}),
|
|
32
|
+
/* @__PURE__ */s("div",{className:"flex flex-col items-center gap-2",children:[
|
|
33
|
+
/* @__PURE__ */s("button",{onClick:r,className:"px-4 py-2 bg-blue-500 text-white text-sm rounded hover:bg-blue-600 inline-flex items-center gap-2",children:[
|
|
34
|
+
/* @__PURE__ */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"})}),"Open in a new tab"]}),
|
|
35
|
+
/* @__PURE__ */c("button",{onClick:()=>u(!0),className:"text-xs text-gray-500 hover:text-gray-800 underline",children:"Try loading it here anyway"})]})]})}):/* @__PURE__ */s(m,{children:[
|
|
36
|
+
/* @__PURE__ */c("iframe",{ref:o,src:e,className:"absolute inset-0 w-full h-full bg-white",sandbox:"allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals",referrerPolicy:"no-referrer-when-downgrade"},t+e),n&&/* @__PURE__ */s("div",{className:"absolute top-2 right-2 max-w-sm bg-white border border-gray-200 rounded-md shadow-lg p-3 text-xs text-gray-700 z-10",children:[
|
|
37
|
+
/* @__PURE__ */c("div",{className:"font-medium text-gray-900 mb-1",children:"Why is this page blank?"}),
|
|
38
|
+
/* @__PURE__ */s("p",{className:"mb-2",children:["Most major sites (Google, GitHub, banks, news) refuse to be embedded in an iframe via ",
|
|
39
|
+
/* @__PURE__ */c("span",{className:"font-mono",children:"X-Frame-Options"})," or Content Security Policy. There's no workaround — the browser blocks the load before our app can do anything."]}),
|
|
40
|
+
/* @__PURE__ */s("p",{children:["Hit the ",
|
|
41
|
+
/* @__PURE__ */c("span",{className:"font-medium",children:"↗"})," button to open the page in a real new tab. Sites that ",
|
|
42
|
+
/* @__PURE__ */c("em",{children:"do"})," allow embedding (Wikipedia, DevDocs, your own apps) work fine in here."]}),
|
|
43
|
+
/* @__PURE__ */c("button",{onClick:a,className:"mt-2 text-[11px] text-blue-600 hover:underline",children:"Got it"})]})]})}export{w as default};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-H562R4GX.js";import{useWidgetSettings as n}from"./chunk-JN4WXTWJ.js";import"./chunk-UB4JIOLD.js";import"./chunk-44UO7FYU.js";import"./chunk-PH3PRIFP.js";import"./chunk-UZAJ5BF6.js";import"./chunk-3A46NCXK.js";import"./chunk-57MIENLJ.js";import"./chunk-OQDWLHZI.js";import"./chunk-MAIHBBWT.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(""),[N,y]=l([]),[f,C]=l(!1),[$,j]=l(()=>e(s)),[w,L]=l(!1),[E,B]=l($);n(r(()=>{B({...$}),L(!0)},[$]));const T=r(e=>{v(""),d(t=>g||"0"===t?(p(!1),"."===e?"0.":e):"."===e&&t.includes(".")?t:t+e)},[g]),W=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]),A=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)),v(n),d(String(t)),m(null),k(null),p(!0)},[u,h,b,F]),I=r(()=>{d(e=>String(parseFloat(e)/100))},[]),J=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?S("+"):"-"===e.key?S("-"):"*"===e.key?S("×"):"/"===e.key?(e.preventDefault(),S("÷")):"Enter"===e.key||"="===e.key?A():"Escape"===e.key?W():"Backspace"===e.key?d(e=>e.length>1?e.slice(0,-1):"0"):"%"===e.key&&I())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[T,S,A,W,I]);const H="flex items-center justify-center rounded-lg text-sm font-medium transition-colors",M=`${H} bg-white border border-gray-200 text-gray-900 hover:bg-gray-50 active:bg-gray-100`,O=`${H} bg-blue-50 border border-blue-200 text-blue-700 hover:bg-blue-100 active:bg-blue-200`,U=`${H} bg-gray-100 border border-gray-200 text-gray-600 hover:bg-gray-200 active:bg-gray-300`,D=`${H} bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800`;/* @__PURE__ */
|
|
2
|
+
return o(a,{children:[
|
|
3
|
+
/* @__PURE__ */o("div",{className:"flex flex-col h-full",style:{opacity:$.activeOpacity/100,backdropFilter:$.activeBlur>0?`blur(${$.activeBlur}px)`:void 0},children:[
|
|
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:N.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
|
+
/* @__PURE__ */o("div",{className:"flex items-center gap-2",children:[
|
|
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
|
+
/* @__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
|
+
/* @__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:W,className:U,children:"AC"}),
|
|
11
|
+
/* @__PURE__ */c("button",{onClick:J,className:U,children:"+/−"}),
|
|
12
|
+
/* @__PURE__ */c("button",{onClick:I,className:U,children:"%"}),
|
|
13
|
+
/* @__PURE__ */c("button",{onClick:()=>S("÷"),className:`${O} ${"÷"===b?"ring-2 ring-blue-400":""}`,children:"÷"}),
|
|
14
|
+
/* @__PURE__ */c("button",{onClick:()=>T("7"),className:M,children:"7"}),
|
|
15
|
+
/* @__PURE__ */c("button",{onClick:()=>T("8"),className:M,children:"8"}),
|
|
16
|
+
/* @__PURE__ */c("button",{onClick:()=>T("9"),className:M,children:"9"}),
|
|
17
|
+
/* @__PURE__ */c("button",{onClick:()=>S("×"),className:`${O} ${"×"===b?"ring-2 ring-blue-400":""}`,children:"×"}),
|
|
18
|
+
/* @__PURE__ */c("button",{onClick:()=>T("4"),className:M,children:"4"}),
|
|
19
|
+
/* @__PURE__ */c("button",{onClick:()=>T("5"),className:M,children:"5"}),
|
|
20
|
+
/* @__PURE__ */c("button",{onClick:()=>T("6"),className:M,children:"6"}),
|
|
21
|
+
/* @__PURE__ */c("button",{onClick:()=>S("-"),className:`${O} ${"-"===b?"ring-2 ring-blue-400":""}`,children:"−"}),
|
|
22
|
+
/* @__PURE__ */c("button",{onClick:()=>T("1"),className:M,children:"1"}),
|
|
23
|
+
/* @__PURE__ */c("button",{onClick:()=>T("2"),className:M,children:"2"}),
|
|
24
|
+
/* @__PURE__ */c("button",{onClick:()=>T("3"),className:M,children:"3"}),
|
|
25
|
+
/* @__PURE__ */c("button",{onClick:()=>S("+"),className:`${O} ${"+"===b?"ring-2 ring-blue-400":""}`,children:"+"}),
|
|
26
|
+
/* @__PURE__ */c("button",{onClick:()=>T("0"),className:`${M} col-span-2`,children:"0"}),
|
|
27
|
+
/* @__PURE__ */c("button",{onClick:()=>T("."),className:M,children:"."}),
|
|
28
|
+
/* @__PURE__ */c("button",{onClick:A,className:D,children:"="})]})]}),
|
|
29
|
+
/* @__PURE__ */c(t,{open:w,onClose:()=>L(!1),title:"Calculator Settings",appearance:E,onAppearanceChange:B,onSave:()=>{j(E),localStorage.setItem(s,JSON.stringify(E)),L(!1)}})]})}export{u as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ConfirmProvider,confirm,confirmDestructive,prompt,useConfirm}from"./chunk-3A46NCXK.js";import"./chunk-OQDWLHZI.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import{loadAppearance as e,WidgetSettingsModal as t}from"./chunk-H562R4GX.js";import{useWidgetSettings as r}from"./chunk-JN4WXTWJ.js";import"./chunk-UB4JIOLD.js";import"./chunk-44UO7FYU.js";import"./chunk-PH3PRIFP.js";import"./chunk-UZAJ5BF6.js";import"./chunk-3A46NCXK.js";import"./chunk-57MIENLJ.js";import"./chunk-OQDWLHZI.js";import"./chunk-MAIHBBWT.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,J]=a([]),[U,B]=a(f),[I,A]=a("USD"),[H,O]=a("CNY");r(n(()=>{J([...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
|
+
return c(o,{children:[
|
|
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
|
+
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:[
|
|
5
|
+
/* @__PURE__ */c("div",{className:"flex items-center gap-1.5",children:[
|
|
6
|
+
/* @__PURE__ */i("span",{className:"text-base",children:y[e]||""}),
|
|
7
|
+
/* @__PURE__ */i("span",{className:"text-sm font-semibold text-gray-700",children:e}),
|
|
8
|
+
/* @__PURE__ */i("svg",{className:"h-3 w-3 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */i("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"})}),
|
|
9
|
+
/* @__PURE__ */i("span",{className:"text-base",children:y[t]||""}),
|
|
10
|
+
/* @__PURE__ */i("span",{className:"text-sm font-semibold text-gray-700",children:t})]}),
|
|
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:U,onAppearanceChange:B,onSave:()=>{if(0===j.length)return;const e=j.slice(0,4);p(e),N(U),localStorage.setItem(d,JSON.stringify(e)),localStorage.setItem(u,JSON.stringify(U)),C(!1)},children:/* @__PURE__ */c("div",{children:[
|
|
13
|
+
/* @__PURE__ */c("h3",{className:"text-sm font-semibold text-gray-700 mb-2",children:["Currency Pairs ",
|
|
14
|
+
/* @__PURE__ */c("span",{className:"text-[11px] font-normal text-gray-400",children:["(",j.length,"/",4,")"]})]}),
|
|
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
|
+
/* @__PURE__ */c("span",{className:"text-sm",children:[y[e]||""," ",e," → ",y[t]||""," ",t]}),
|
|
17
|
+
/* @__PURE__ */i("button",{onClick:()=>J(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:I,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))}),
|
|
19
|
+
/* @__PURE__ */i("span",{className:"text-gray-400",children:"→"}),
|
|
20
|
+
/* @__PURE__ */i("select",{value:H,onChange:e=>O(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!==H&&j.length<4&&J(e=>[...e,[I,H]])},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};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import{AboutApp as e}from"./chunk-TAWKWSPN.js";import{WindowTitle as t}from"./chunk-JN4WXTWJ.js";import"./chunk-UB4JIOLD.js";import{escapeHtml as n}from"./chunk-BR22X7E5.js";import"./chunk-U4GTZPXP.js";import{toast_default as r}from"./chunk-VEGMDXT4.js";import"./chunk-44UO7FYU.js";import"./chunk-PH3PRIFP.js";import{PopupMenu as o,PopupMenuLabel as l,PopupMenuItem as a,PopupMenuDivider as i}from"./chunk-UZAJ5BF6.js";import"./chunk-3A46NCXK.js";import"./chunk-57MIENLJ.js";import"./chunk-OQDWLHZI.js";import"./chunk-MAIHBBWT.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),D=c(null),j=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)}},B=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))},W=async e=>{const t=(e.name.split(".").pop()||"").toLowerCase();y(!0);try{if(m.has(t)||!u.has(t)&&e.type.startsWith("text/")){const r=await e.text(),o=n(r).replace(/\n/g,"<br>");x({filename:e.name,kind:"text",content:o,ext:t}),w(!1)}else if(u.has(t))try{const n=await(import(
|
|
2
|
+
/* @vite-ignore */
|
|
3
|
+
"mammoth")),r=await e.arrayBuffer(),o=await n.convertToHtml({arrayBuffer:r});x({filename:e.name,kind:"docx",content:o.value||"<p><em>(empty document)</em></p>",ext:t}),w(!1)}catch(e){r.error('Install the optional "mammoth" peer dep to read .docx files.')}else"doc"===t?r.error(".doc is the legacy Word binary format — convert to .docx first."):r.error(`Unsupported file type: .${t||"unknown"}`)}finally{y(!1)}},R=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):W(t[0]))},children:[
|
|
5
|
+
/* @__PURE__ */h(t,{title:`${R}${k?" •":""} - Documents`}),
|
|
6
|
+
/* @__PURE__ */h(e,{app:"documents"}),
|
|
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:D,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&&W(t),D.current&&(D.current.value="")},className:"hidden"}),
|
|
9
|
+
/* @__PURE__ */d("button",{onClick:()=>D.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
|
+
/* @__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
|
+
/* @__PURE__ */h("button",{onClick:()=>{if(!g)return;const e=L.current?.innerHTML??"";if("text"===g.kind){if(/<(b|strong|i|em|u|font|span style|ul|ol|img)|style="[^"]*text-align/i.test(e)){const t=new Blob([`<!doctype html><meta charset="utf-8"><title>${n(g.filename)}</title><body style="font-family:ui-monospace,monospace;white-space:pre-wrap">${e}`],{type:"text/html"}),r=URL.createObjectURL(t),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 t=new Blob([`<!doctype html><meta charset="utf-8"><title>${n(g.filename)}</title>${e}`],{type:"text/html"}),r=URL.createObjectURL(t),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"}),
|
|
12
|
+
/* @__PURE__ */h("span",{className:"text-[10px] text-gray-400 ml-1",children:"TXT · DOCX · Code"}),
|
|
13
|
+
/* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
14
|
+
/* @__PURE__ */d("span",{className:"text-xs font-medium text-gray-700 truncate max-w-[200px]",title:g.filename,children:[g.filename,k?" •":""]}),
|
|
15
|
+
/* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
16
|
+
/* @__PURE__ */d("div",{className:"flex items-center gap-0.5",children:[
|
|
17
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("bold"),className:"px-2 py-1 text-xs rounded font-bold text-gray-700 hover:bg-gray-200 transition-colors",title:"Bold",children:"B"}),
|
|
18
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("italic"),className:"px-2 py-1 text-xs rounded italic text-gray-700 hover:bg-gray-200 transition-colors",title:"Italic",children:"I"}),
|
|
19
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("underline"),className:"px-2 py-1 text-xs rounded underline text-gray-700 hover:bg-gray-200 transition-colors",title:"Underline",children:"U"}),
|
|
20
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("strikeThrough"),className:"px-2 py-1 text-xs rounded line-through text-gray-700 hover:bg-gray-200 transition-colors",title:"Strikethrough",children:"S"})]}),
|
|
21
|
+
/* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
22
|
+
/* @__PURE__ */d("select",{onMouseDown:e=>e.preventDefault(),onChange:e=>{M("fontSize",e.target.value),e.currentTarget.value=""},defaultValue:"",className:"text-xs border border-gray-300 rounded px-1 py-0.5 bg-white",children:[
|
|
23
|
+
/* @__PURE__ */h("option",{value:"",disabled:!0,children:"Size"}),
|
|
24
|
+
/* @__PURE__ */h("option",{value:"1",children:"XS"}),
|
|
25
|
+
/* @__PURE__ */h("option",{value:"2",children:"S"}),
|
|
26
|
+
/* @__PURE__ */h("option",{value:"3",children:"M"}),
|
|
27
|
+
/* @__PURE__ */h("option",{value:"4",children:"L"}),
|
|
28
|
+
/* @__PURE__ */h("option",{value:"5",children:"XL"}),
|
|
29
|
+
/* @__PURE__ */h("option",{value:"6",children:"2XL"})]}),
|
|
30
|
+
/* @__PURE__ */h("input",{type:"color",defaultValue:"#000000",onChange:e=>M("foreColor",e.target.value),className:"w-7 h-6 border border-gray-300 rounded cursor-pointer",title:"Text color"}),
|
|
31
|
+
/* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
32
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("insertUnorderedList"),className:"px-2 py-1 text-xs rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Bulleted list",children:"• List"}),
|
|
33
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("insertOrderedList"),className:"px-2 py-1 text-xs rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Numbered list",children:"1."}),
|
|
34
|
+
/* @__PURE__ */h("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
35
|
+
/* @__PURE__ */d("div",{className:"flex items-center gap-0.5",children:[
|
|
36
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("justifyLeft"),className:"px-2 py-1 rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Align left",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 12h9.75M3.75 18h14.25"})})}),
|
|
37
|
+
/* @__PURE__ */h("button",{onMouseDown:e=>e.preventDefault(),onClick:()=>M("justifyCenter"),className:"px-2 py-1 rounded text-gray-700 hover:bg-gray-200 transition-colors",title:"Align center",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.5M7.125 12h9.75M4.875 18h14.25"})})}),
|
|
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
|
+
/* @__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
|
+
/* @__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="")}}),
|
|
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
|
+
/* @__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:L,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:[
|
|
45
|
+
/* @__PURE__ */h(l,{children:"Image width"}),
|
|
46
|
+
/* @__PURE__ */h(a,{onClick:()=>B("25%"),children:"25%"}),
|
|
47
|
+
/* @__PURE__ */h(a,{onClick:()=>B("50%"),children:"50%"}),
|
|
48
|
+
/* @__PURE__ */h(a,{onClick:()=>B("75%"),children:"75%"}),
|
|
49
|
+
/* @__PURE__ */h(a,{onClick:()=>B("100%"),children:"100%"}),
|
|
50
|
+
/* @__PURE__ */h(a,{onClick:()=>B(null),children:"Original size"}),
|
|
51
|
+
/* @__PURE__ */h(i,{}),
|
|
52
|
+
/* @__PURE__ */h(a,{danger:!0,onClick:()=>{N?.el.remove(),w(!0),C(null)},children:"Remove image"})]})]})}export{g as default};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import{openPreviewFile as e}from"./chunk-466CM2TJ.js";import{getFilesDemoTree as t}from"./chunk-FHTLC7HH.js";import{AboutApp as r}from"./chunk-TAWKWSPN.js";import{peekFilesViewRequest as a,consumeFilesViewRequest as n,FILES_SHOW_TRASH_EVENT as i,FILES_OPEN_DESKTOP_FOLDER_EVENT as o,subscribeDesktopFolders as s,getDesktopFoldersSnapshot as l,FolderGlyph as d,DesktopItemMiniIcon as c,desktopItemTypeLabel as m}from"./chunk-NPJH5MD7.js";import"./chunk-ESL5TDNA.js";import"./chunk-VTVSMRFX.js";import{useWindowManager as h,WindowTitle as p}from"./chunk-JN4WXTWJ.js";import"./chunk-UB4JIOLD.js";import{Breadcrumbs as u}from"./chunk-A2OQLLYK.js";import{SidebarLayout as f}from"./chunk-B43AGQET.js";import"./chunk-U4GTZPXP.js";import{toast_default as x}from"./chunk-VEGMDXT4.js";import"./chunk-44UO7FYU.js";import"./chunk-PH3PRIFP.js";import"./chunk-UZAJ5BF6.js";import{confirm as g,prompt as y}from"./chunk-3A46NCXK.js";import"./chunk-57MIENLJ.js";import"./chunk-OQDWLHZI.js";import"./chunk-MAIHBBWT.js";import"./chunk-D65T4H6J.js";import{useState as b,useEffect as k,useSyncExternalStore as v,useRef as w,useCallback as N}from"react";import{jsxs as L,jsx as j,Fragment as C}from"react/jsx-runtime";var $="undefined"!=typeof window&&window.__REACT_OS_SHELL_FILE_SERVER__||"http://localhost:4000",M={pdf:"pdf",dxf:"dxf",csv:"csv",jpg:"image",jpeg:"image",png:"image",gif:"image",webp:"image",svg:"image",avif:"image",bmp:"image",stp:"3d",step:"3d",stl:"3d",obj:"3d",gltf:"3d",glb:"3d","3mf":"3d",iges:"3d",igs:"3d",ply:"3d",fbx:"3d"};function T(e,t){return"/"===e||""===e?"/"+t:e.replace(/\/$/,"")+"/"+t}function D(e){if(!e)return"—";const t=["B","KB","MB","GB"];let r=e,a=0;for(;r>=1024&&a<t.length-1;)r/=1024,a++;return`${r<10?r.toFixed(1):Math.round(r)} ${t[a]}`}function E(e){if(!e)return"—";try{const t=new Date(e);return isNaN(t.getTime())?"—":t.toLocaleString(void 0,{dateStyle:"short",timeStyle:"short"})}catch{return e}}function A(){const A=$.replace(/\/$/,""),B=null!==t(),[P,R]=b("/"),[F,I]=b([]),[W,H]=b([]),[S,O]=b(null),[U,V]=b(!0),[z,J]=b(!1),[_,K]=b(null),[X,G]=b(!1),[Q,Z]=b(()=>{const e=a();return"trash"===e?"trash":e?{desktopFolderId:e.folderId}:"files"});k(()=>{n()},[]);const[Y,q]=b([]);k(()=>{const e=()=>{n(),Z("trash")},t=e=>{n();const t=e.detail?.folderId;t&&Z({desktopFolderId:t})};return window.addEventListener(i,e),window.addEventListener(o,t),()=>{window.removeEventListener(i,e),window.removeEventListener(o,t)}},[]);const ee=v(s,l,l),te="object"==typeof Q?Q.desktopFolderId:null,re=te?ee?.folders.find(e=>e.id===te)??null:null,ae=te&&ee?.itemsByFolder[te]||[];k(()=>{te&&ee&&!ee.folders.some(e=>e.id===te)&&Z("files")},[te,ee]);const ne=w(0),ie=w(null),{openPage:oe,openEntity:se}=h(),le=t=>{"preview-file"===t.entityType&&t.filePath&&t.fileKind?e({filePath:t.filePath,filename:t.label,kind:t.fileKind,onStaged:e=>oe(e)}):"page"===t.entityType?oe(t.entityId):se(t.entityType,t.entityId,null,t.label)},de=N((e,t={})=>fetch(e,{...t,credentials:"include"}),[]),ce=N(async()=>{try{const e=await de(`${A}/api/quota`);if(e.ok){const t=await e.json();K({used:t.used,limit:t.limit})}}catch{}},[de,A]),me=N(async e=>{if(O(null),B){const r=function(e){const r=t();if(!r)return[];let a=r;for(const t of e.split("/").filter(Boolean)){const e=a.find(e=>"folder"===e.kind&&e.name===t);if(!e||!e.children)return[];a=e.children}return a.map(e=>({name:e.name,kind:e.kind,size:e.size??0,modifiedAt:e.modifiedAt??""}))}(e);return I(r),R(e),J(!1),V(!1),void("/"===e&&H(r.filter(e=>"folder"===e.kind).map(e=>e.name)))}V(!0);try{const t=await de(`${A}/api/files?path=${encodeURIComponent(e)}`);if(!t.ok){const e=await t.json().catch(()=>({}));return void x.error(e.error||`Failed to list (${t.status})`)}const r=await t.json(),a=r.entries||[];I(a),R(r.path||e),J(!1),"/"===(r.path||e)&&H(a.filter(e=>"folder"===e.kind).map(e=>e.name))}catch(e){J(!0)}finally{V(!1)}ce()},[de,A,ce,B]),he=N(async()=>{if(B)return q([]),void V(!1);V(!0),O(null);try{const e=await de(`${A}/api/trash`);if(!e.ok){const t=await e.json().catch(()=>({}));return void x.error(t.error||`Failed to list trash (${e.status})`)}const t=await e.json();q(t.entries||[]),J(!1)}catch{J(!0)}finally{V(!1)}ce()},[de,A,ce,B]);k(()=>{"files"===Q?me(P):"trash"===Q&&he()},[P,Q]);const pe=async e=>{const t=T(P,e.name);try{const r=await de(`${A}/api/file?path=${encodeURIComponent(t)}`);if(!r.ok)return void x.error(`Download failed (${r.status})`);const a=await r.blob(),n=URL.createObjectURL(a),i=document.createElement("a");i.href=n,i.download=e.name,i.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}catch(e){x.error(e?.message||"Download failed")}},ue=async e=>{const t=Array.from(e);for(const e of t){const t=new FormData;t.append("file",e);try{const r=await de(`${A}/api/upload?path=${encodeURIComponent(P)}`,{method:"POST",body:t});if(!r.ok){const t=await r.json().catch(()=>({}));if(413===r.status){const r=Math.max(0,(t.limit||0)-(t.used||0));x.error(`Quota exceeded — ${D(r)} free, ${e.name} is ${D(t.attempted||e.size)}`)}else x.error(`Upload ${e.name}: ${t.error||r.status}`)}}catch(t){x.error(`Upload ${e.name}: ${t?.message||"failed"}`)}}me(P)},fe=()=>{ne.current=0,G(!1)};if(k(()=>{const e=()=>fe();return window.addEventListener("dragend",e),window.addEventListener("drop",e),()=>{window.removeEventListener("dragend",e),window.removeEventListener("drop",e)}},[]),z)/* @__PURE__ */
|
|
2
|
+
return L("div",{className:"flex flex-col h-full bg-white",children:[
|
|
3
|
+
/* @__PURE__ */j(p,{title:"Files - offline"}),
|
|
4
|
+
/* @__PURE__ */j("div",{className:"flex-1 flex items-center justify-center p-8 text-center",children:/* @__PURE__ */L("div",{className:"max-w-md",children:[
|
|
5
|
+
/* @__PURE__ */L("svg",{className:"h-12 w-12 mx-auto text-gray-300 mb-3",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.4,children:[
|
|
6
|
+
/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.364 5.636l-12.728 12.728M5.636 5.636l12.728 12.728"}),
|
|
7
|
+
/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 21a9 9 0 100-18 9 9 0 000 18z"})]}),
|
|
8
|
+
/* @__PURE__ */j("h3",{className:"text-base font-semibold text-gray-800 mb-1",children:"Can't reach the file server"}),
|
|
9
|
+
/* @__PURE__ */L("p",{className:"text-sm text-gray-500 mb-3",children:["No response from ",
|
|
10
|
+
/* @__PURE__ */j("span",{className:"font-mono",children:A}),". Make sure the server is running — see ",
|
|
11
|
+
/* @__PURE__ */j("span",{className:"font-mono",children:"examples/file-server/README.md"}),"."]}),
|
|
12
|
+
/* @__PURE__ */j("button",{onClick:()=>me(P),className:"px-3 py-1.5 text-sm bg-blue-500 text-white rounded hover:bg-blue-600",children:"Retry"})]})})]});const xe="/"===P?[]:P.split("/").filter(Boolean),ge=_&&_.limit>0?Math.min(100,Math.round(_.used/_.limit*100)):0,ye=ge>90?"bg-red-500":ge>75?"bg-amber-500":"bg-blue-500",be=[{label:"My files",onClick:()=>R("/")},...xe.map((e,t)=>({label:e,onClick:()=>R("/"+xe.slice(0,t+1).join("/"))}))],ke=e=>"flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors "+(e?"bg-blue-50 font-medium text-blue-700":"text-gray-700 hover:bg-gray-100"),ve=e=>/* @__PURE__ */j("svg",{className:"h-4 w-4 shrink-0 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.6,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:e})}),we=/* @__PURE__ */L("nav",{className:"p-2",children:[
|
|
13
|
+
/* @__PURE__ */j("div",{className:"px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400",children:"Locations"}),
|
|
14
|
+
/* @__PURE__ */L("button",{onClick:()=>{Z("files"),R("/")},className:ke("files"===Q&&"/"===P),children:[ve("M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0L21.75 12M4.5 9.75v9.75a.75.75 0 00.75.75H9V15a.75.75 0 01.75-.75h4.5A.75.75 0 0115 15v5.25h3.75a.75.75 0 00.75-.75V9.75"),"My files"]}),W.map(e=>/* @__PURE__ */L("button",{onClick:()=>{Z("files"),R("/"+e)},className:ke("files"===Q&&P==="/"+e),children:[ve("M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"),
|
|
15
|
+
/* @__PURE__ */j("span",{className:"truncate",children:e})]},e)),!B&&/* @__PURE__ */L("button",{onClick:()=>Z("trash"),className:ke("trash"===Q),children:[ve("M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79"),"Trash"]}),ee&&ee.folders.length>0&&/* @__PURE__ */L(C,{children:[
|
|
16
|
+
/* @__PURE__ */j("div",{className:"px-2 pt-3 pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400",children:"Desktop"}),ee.folders.map(e=>/* @__PURE__ */L("button",{onClick:()=>Z({desktopFolderId:e.id}),className:ke(te===e.id),children:[
|
|
17
|
+
/* @__PURE__ */j(d,{className:"h-4 w-4 shrink-0 text-amber-500"}),
|
|
18
|
+
/* @__PURE__ */j("span",{className:"truncate",children:e.name}),e.itemCount>0&&/* @__PURE__ */j("span",{className:"ml-auto text-[10px] text-gray-400 tabular-nums",children:e.itemCount})]},e.id))]})]});/* @__PURE__ */
|
|
19
|
+
return L("div",{className:"relative flex flex-col h-full bg-white",onDragEnter:e=>{B||"object"==typeof Q||e.dataTransfer?.types?.includes?.("Files")&&(e.preventDefault(),ne.current++,X||G(!0))},onDragOver:e=>{e.dataTransfer?.types?.includes?.("Files")&&e.preventDefault()},onDragLeave:()=>{ne.current>0&&ne.current--,0===ne.current&&G(!1)},onDrop:e=>{e.preventDefault(),fe(),B||"object"==typeof Q||e.dataTransfer.files?.length&&ue(e.dataTransfer.files)},children:[
|
|
20
|
+
/* @__PURE__ */j(p,{title:re?`Files - ${re.name}`:"Files"+("/"===P?"":" - "+P)}),
|
|
21
|
+
/* @__PURE__ */j(r,{app:"files"}),
|
|
22
|
+
/* @__PURE__ */j("input",{ref:ie,type:"file",multiple:!0,className:"hidden",onChange:e=>{e.target.files?.length&&ue(e.target.files),ie.current&&(ie.current.value="")}}),
|
|
23
|
+
/* @__PURE__ */j("div",{className:"flex-1 min-h-0",children:/* @__PURE__ */j(f,{sidebar:we,storageKey:"files.sidebarWidth",defaultWidth:200,minWidth:150,maxWidth:320,children:/* @__PURE__ */L("div",{className:"flex h-full min-w-0 flex-col",children:[
|
|
24
|
+
/* @__PURE__ */L("div",{className:"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0 text-xs",children:[/* @__PURE__ */L(C,"files"===Q?{children:[
|
|
25
|
+
/* @__PURE__ */j("button",{onClick:()=>R(function(e){if("/"===e||""===e)return"/";const t=e.replace(/\/$/,""),r=t.lastIndexOf("/");return r<=0?"/":t.slice(0,r)}(P)),disabled:"/"===P,className:"px-2 py-1 rounded hover:bg-gray-200 disabled:opacity-30 text-gray-600",title:"Parent folder",children:/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"})})}),
|
|
26
|
+
/* @__PURE__ */j("div",{className:"flex-1 min-w-0",children:/* @__PURE__ */j(u,{items:be,maxItems:5})}),
|
|
27
|
+
/* @__PURE__ */j("button",{onClick:()=>me(P),className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600",title:"Refresh",children:/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */j("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"})})}),!B&&/* @__PURE__ */L(C,{children:[
|
|
28
|
+
/* @__PURE__ */L("button",{onClick:()=>Z("trash"),className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1",title:"Open trash",children:[
|
|
29
|
+
/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"})}),"Trash"]}),
|
|
30
|
+
/* @__PURE__ */L("button",{onClick:async()=>{const e=await y({title:"New folder",placeholder:"Folder name",confirmLabel:"Create"});if(!e)return;if(/[\\/]/.test(e))return void x.error("Folder names cannot contain slashes");const t=T(P,e),r=await de(`${A}/api/folder`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!r.ok){const e=await r.json().catch(()=>({}));return void x.error(e.error||`Create folder failed (${r.status})`)}me(P)},className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1",children:[
|
|
31
|
+
/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 10.5v6m3-3H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"})}),"New Folder"]}),
|
|
32
|
+
/* @__PURE__ */L("button",{onClick:()=>ie.current?.click(),className:"px-2 py-1 rounded bg-blue-500 text-white hover:bg-blue-600 flex items-center gap-1",children:[
|
|
33
|
+
/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M7.5 7.5L12 3m0 0l4.5 4.5M12 3v13.5"})}),"Upload"]})]})]}:"trash"===Q?{children:[
|
|
34
|
+
/* @__PURE__ */j("button",{onClick:()=>Z("files"),className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600",title:"Back to files",children:/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"})})}),
|
|
35
|
+
/* @__PURE__ */j("span",{className:"flex-1 text-gray-700 font-medium px-2",children:"Trash"}),
|
|
36
|
+
/* @__PURE__ */j("button",{onClick:he,className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600",title:"Refresh",children:/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.8,children:/* @__PURE__ */j("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"})})}),
|
|
37
|
+
/* @__PURE__ */j("button",{onClick:async()=>{if(0===Y.length)return;if(!await g({title:"Empty trash",message:`${Y.length} item${1===Y.length?"":"s"} will be permanently removed. This can't be undone.`,confirmLabel:"Empty trash",variant:"danger"}))return;const e=await de(`${A}/api/trash`,{method:"DELETE"});if(!e.ok){const t=await e.json().catch(()=>({}));return void x.error(t.error||`Empty trash failed (${e.status})`)}he()},disabled:0===Y.length,className:"px-2 py-1 rounded text-red-600 hover:bg-red-50 disabled:opacity-30 flex items-center gap-1",children:"Empty trash"})]}:{children:[
|
|
38
|
+
/* @__PURE__ */j("button",{onClick:()=>Z("files"),className:"px-2 py-1 rounded hover:bg-gray-200 text-gray-600",title:"Back to files",children:/* @__PURE__ */j("svg",{className:"h-3.5 w-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"})})}),
|
|
39
|
+
/* @__PURE__ */j(d,{className:"h-4 w-4 text-amber-500 ml-1"}),
|
|
40
|
+
/* @__PURE__ */j("span",{className:"flex-1 text-gray-700 font-medium px-1 truncate",children:re?.name??"Desktop folder"}),
|
|
41
|
+
/* @__PURE__ */j("span",{className:"text-[10px] text-gray-400 px-2",children:"Desktop shortcuts"})]}),_&&/* @__PURE__ */L(C,{children:[
|
|
42
|
+
/* @__PURE__ */j("div",{className:"h-4 w-px bg-gray-300 mx-1"}),
|
|
43
|
+
/* @__PURE__ */L("div",{className:"flex items-center gap-1.5",title:`${D(_.used)} of ${D(_.limit)} used`,children:[
|
|
44
|
+
/* @__PURE__ */j("div",{className:"w-20 h-1.5 rounded-full bg-gray-200 overflow-hidden",children:/* @__PURE__ */j("div",{className:`h-full ${ye} transition-all`,style:{width:`${ge}%`}})}),
|
|
45
|
+
/* @__PURE__ */L("span",{className:"text-[10px] text-gray-500 tabular-nums whitespace-nowrap",children:[D(_.used)," / ",D(_.limit)]})]})]})]}),
|
|
46
|
+
/* @__PURE__ */j("div",{className:"flex-1 overflow-auto",children:"object"==typeof Q?0===ae.length?/* @__PURE__ */j("div",{className:"p-10 text-center text-sm text-gray-400",children:"This desktop folder is empty. Drag shortcuts onto it on the desktop."}):/* @__PURE__ */L("table",{className:"w-full text-sm",children:[
|
|
47
|
+
/* @__PURE__ */j("thead",{className:"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500",children:/* @__PURE__ */L("tr",{children:[
|
|
48
|
+
/* @__PURE__ */j("th",{className:"text-left font-medium px-3 py-1.5",children:"Name"}),
|
|
49
|
+
/* @__PURE__ */j("th",{className:"text-left font-medium px-3 py-1.5 w-28",children:"Type"}),
|
|
50
|
+
/* @__PURE__ */j("th",{className:"w-56"})]})}),
|
|
51
|
+
/* @__PURE__ */j("tbody",{children:ae.map(e=>{const t=`${e.entityType}|${e.entityId}`;/* @__PURE__ */
|
|
52
|
+
return L("tr",{onClick:()=>O(t),onDoubleClick:()=>le(e),className:"cursor-default border-b border-gray-100 "+(S===t?"bg-blue-50":"hover:bg-gray-50"),children:[
|
|
53
|
+
/* @__PURE__ */L("td",{className:"px-3 py-1.5 flex items-center gap-2",children:[
|
|
54
|
+
/* @__PURE__ */j(c,{item:e}),
|
|
55
|
+
/* @__PURE__ */j("span",{className:"truncate",title:e.label,children:e.label})]}),
|
|
56
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-xs text-gray-500",children:m(e)}),
|
|
57
|
+
/* @__PURE__ */L("td",{className:"px-3 py-1.5 text-right whitespace-nowrap",children:[
|
|
58
|
+
/* @__PURE__ */j("button",{onClick:t=>{t.stopPropagation(),le(e)},className:"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]",children:"Open"}),
|
|
59
|
+
/* @__PURE__ */j("button",{onClick:t=>{t.stopPropagation(),ee?.moveToDesktop([e])},className:"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1",children:"Move to desktop"}),
|
|
60
|
+
/* @__PURE__ */j("button",{onClick:t=>{t.stopPropagation(),ee?.removeShortcuts([e])},className:"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1",children:"Remove"})]})]},t)})})]}):"trash"===Q?U&&0===Y.length?/* @__PURE__ */j("div",{className:"p-6 text-center text-sm text-gray-400",children:"Loading…"}):0===Y.length?/* @__PURE__ */j("div",{className:"p-10 text-center text-sm text-gray-400",children:"Trash is empty."}):/* @__PURE__ */L("table",{className:"w-full text-sm",children:[
|
|
61
|
+
/* @__PURE__ */j("thead",{className:"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500",children:/* @__PURE__ */L("tr",{children:[
|
|
62
|
+
/* @__PURE__ */j("th",{className:"text-left font-medium px-3 py-1.5",children:"Name"}),
|
|
63
|
+
/* @__PURE__ */j("th",{className:"text-left font-medium px-3 py-1.5",children:"Original location"}),
|
|
64
|
+
/* @__PURE__ */j("th",{className:"text-right font-medium px-3 py-1.5 w-24",children:"Size"}),
|
|
65
|
+
/* @__PURE__ */j("th",{className:"text-right font-medium px-3 py-1.5 w-40",children:"Deleted"}),
|
|
66
|
+
/* @__PURE__ */j("th",{className:"w-44"})]})}),
|
|
67
|
+
/* @__PURE__ */j("tbody",{children:Y.map(e=>/* @__PURE__ */L("tr",{className:"border-b border-gray-100 hover:bg-gray-50",children:[
|
|
68
|
+
/* @__PURE__ */L("td",{className:"px-3 py-1.5 flex items-center gap-2",children:["folder"===e.kind?/* @__PURE__ */j("svg",{className:"h-4 w-4 text-amber-500 shrink-0",fill:"currentColor",viewBox:"0 0 24 24",children:/* @__PURE__ */j("path",{d:"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z"})}):/* @__PURE__ */j("svg",{className:"h-4 w-4 text-gray-400 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"})}),
|
|
69
|
+
/* @__PURE__ */j("span",{className:"truncate",title:e.name,children:e.name})]}),
|
|
70
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-gray-500 text-xs font-mono truncate",title:e.originalPath,children:e.originalPath||"—"}),
|
|
71
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-right tabular-nums text-gray-500",children:D(e.size)}),
|
|
72
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-right text-gray-500 tabular-nums",children:e.deletedAt?E(e.deletedAt):"—"}),
|
|
73
|
+
/* @__PURE__ */L("td",{className:"px-3 py-1.5 text-right whitespace-nowrap",children:[
|
|
74
|
+
/* @__PURE__ */j("button",{onClick:()=>(async e=>{const t=await de(`${A}/api/trash/restore`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:e.id})});if(!t.ok){const e=await t.json().catch(()=>({}));return void x.error(e.error||`Restore failed (${t.status})`)}x.success(`Restored "${e.name}"`),he()})(e),className:"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]",children:"Restore"}),
|
|
75
|
+
/* @__PURE__ */j("button",{onClick:()=>(async e=>{if(!await g({title:"Permanently delete",message:`"${e.name}" will be permanently removed. This can't be undone.`,confirmLabel:"Delete forever",variant:"danger"}))return;const t=await de(`${A}/api/trash/${encodeURIComponent(e.id)}`,{method:"DELETE"});if(!t.ok){const e=await t.json().catch(()=>({}));return void x.error(e.error||`Delete failed (${t.status})`)}he()})(e),className:"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1",children:"Delete forever"})]})]},e.id))})]}):U&&0===F.length?/* @__PURE__ */j("div",{className:"p-6 text-center text-sm text-gray-400",children:"Loading…"}):0===F.length?/* @__PURE__ */L("div",{className:"p-10 text-center text-sm text-gray-400",children:["Empty folder.",!B&&/* @__PURE__ */L(C,{children:[" Drop files here or click ",
|
|
76
|
+
/* @__PURE__ */j("span",{className:"font-medium",children:"Upload"}),"."]})]}):/* @__PURE__ */L("table",{className:"w-full text-sm",children:[
|
|
77
|
+
/* @__PURE__ */j("thead",{className:"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500",children:/* @__PURE__ */L("tr",{children:[
|
|
78
|
+
/* @__PURE__ */j("th",{className:"text-left font-medium px-3 py-1.5",children:"Name"}),
|
|
79
|
+
/* @__PURE__ */j("th",{className:"text-right font-medium px-3 py-1.5 w-24",children:"Size"}),
|
|
80
|
+
/* @__PURE__ */j("th",{className:"text-right font-medium px-3 py-1.5 w-40",children:"Modified"}),
|
|
81
|
+
/* @__PURE__ */j("th",{className:"w-32"})]})}),
|
|
82
|
+
/* @__PURE__ */j("tbody",{children:F.map(t=>/* @__PURE__ */L("tr",{onClick:()=>O(t.name),onDoubleClick:()=>{"folder"===t.kind?R(T(P,t.name)):(async t=>{if(B)return;const r=T(P,t.name),a=(t.name.split(".").pop()||"").toLowerCase(),n=M[a];n?await e({filePath:r,filename:t.name,kind:n,onStaged:e=>oe(e)}):pe(t)})(t)},className:"cursor-default border-b border-gray-100 "+(S===t.name?"bg-blue-50":"hover:bg-gray-50"),children:[
|
|
83
|
+
/* @__PURE__ */L("td",{className:"px-3 py-1.5 flex items-center gap-2",children:["folder"===t.kind?/* @__PURE__ */j("svg",{className:"h-4 w-4 text-amber-500 shrink-0",fill:"currentColor",viewBox:"0 0 24 24",children:/* @__PURE__ */j("path",{d:"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z"})}):/* @__PURE__ */j("svg",{className:"h-4 w-4 text-gray-400 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:/* @__PURE__ */j("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"})}),
|
|
84
|
+
/* @__PURE__ */j("span",{className:"truncate",title:t.name,children:t.name})]}),
|
|
85
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-right tabular-nums text-gray-500",children:"folder"===t.kind?"—":D(t.size)}),
|
|
86
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-right text-gray-500 tabular-nums",children:E(t.modifiedAt)}),
|
|
87
|
+
/* @__PURE__ */j("td",{className:"px-3 py-1.5 text-right whitespace-nowrap",children:!B&&/* @__PURE__ */L(C,{children:["file"===t.kind&&/* @__PURE__ */j("button",{onClick:e=>{e.stopPropagation(),pe(t)},className:"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px]",children:"Download"}),
|
|
88
|
+
/* @__PURE__ */j("button",{onClick:e=>{e.stopPropagation(),(async e=>{const t=await y({title:`Rename ${e.kind}`,defaultValue:e.name,confirmLabel:"Rename"});if(!t||t===e.name)return;if(/[\\/]/.test(t))return void x.error("Names cannot contain slashes");const r=T(P,e.name),a=T(P,t),n=await de(`${A}/api/rename`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:r,to:a})});if(!n.ok){const e=await n.json().catch(()=>({}));return void x.error(e.error||`Rename failed (${n.status})`)}me(P)})(t)},className:"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1",children:"Rename"}),
|
|
89
|
+
/* @__PURE__ */j("button",{onClick:e=>{e.stopPropagation(),(async e=>{if(!await g({title:`Delete ${e.kind}`,message:`"${e.name}"${"folder"===e.kind?" and everything inside":""} will be permanently removed.`,confirmLabel:"Delete",variant:"danger"}))return;const t=T(P,e.name),r=await de(`${A}/api/files?path=${encodeURIComponent(t)}`,{method:"DELETE"});if(!r.ok){const e=await r.json().catch(()=>({}));return void x.error(e.error||`Delete failed (${r.status})`)}me(P)})(t)},className:"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1",children:"Delete"})]})})]},t.name))})]})})]})})}),X&&/* @__PURE__ */j("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__ */j("div",{className:"px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium shadow-lg",children:"Drop to upload"})})]})}export{A as default};
|