@happyvertical/smrt-svelte 0.55.6 → 0.55.7
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/AGENTS.md +17 -2
- package/README.md +83 -4
- package/agents/workspace.md +202 -5
- package/dist/browser-ai/adapters/stt/dictation-source.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/dictation-source.js +8 -2
- package/dist/browser-ai/adapters/stt/factory.d.ts +6 -3
- package/dist/browser-ai/adapters/stt/factory.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/factory.js +19 -9
- package/dist/browser-ai/adapters/stt/index.d.ts +3 -1
- package/dist/browser-ai/adapters/stt/index.d.ts.map +1 -1
- package/dist/browser-ai/adapters/stt/index.js +3 -1
- package/dist/browser-ai/adapters/stt/local-speech-model.d.ts +111 -0
- package/dist/browser-ai/adapters/stt/local-speech-model.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech-model.js +377 -0
- package/dist/browser-ai/adapters/stt/local-speech.d.ts +82 -0
- package/dist/browser-ai/adapters/stt/local-speech.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech.js +317 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts +2 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/local-speech.worker.js +32 -0
- package/dist/browser-ai/adapters/stt/transformers-env.d.ts +8 -0
- package/dist/browser-ai/adapters/stt/transformers-env.d.ts.map +1 -0
- package/dist/browser-ai/adapters/stt/transformers-env.js +17 -0
- package/dist/browser-ai/adapters/stt/types.d.ts +54 -9
- package/dist/browser-ai/adapters/stt/types.d.ts.map +1 -1
- package/dist/browser-ai/capabilities/speech-probe.d.ts +29 -0
- package/dist/browser-ai/capabilities/speech-probe.d.ts.map +1 -0
- package/dist/browser-ai/capabilities/speech-probe.js +19 -0
- package/dist/browser-ai/core/errors.d.ts +9 -0
- package/dist/browser-ai/core/errors.d.ts.map +1 -1
- package/dist/browser-ai/core/errors.js +12 -0
- package/dist/browser-ai/index.d.ts +1 -0
- package/dist/browser-ai/index.d.ts.map +1 -1
- package/dist/browser-ai/index.js +1 -0
- package/dist/components/app/AppShell.svelte +587 -33
- package/dist/components/app/AppShell.svelte.d.ts +75 -4
- package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
- package/dist/components/app/DockToggles.svelte +0 -1
- package/dist/components/app/dock-toggle.d.ts +7 -1
- package/dist/components/app/dock-toggle.d.ts.map +1 -1
- package/dist/components/app/index.d.ts +2 -1
- package/dist/components/app/index.d.ts.map +1 -1
- package/dist/components/app/slot-item.d.ts +21 -0
- package/dist/components/app/slot-item.d.ts.map +1 -0
- package/dist/components/app/slot-item.js +1 -0
- package/dist/components/forms/AddressInput.svelte +2 -15
- package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateRangeInput.svelte +2 -15
- package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateTimeInput.svelte +8 -15
- package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/MeasurementInput.svelte +2 -15
- package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/MoneyInput.svelte +8 -25
- package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/NumberInput.svelte +7 -15
- package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/PhoneInput.svelte +7 -15
- package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/SelectInput.svelte +34 -40
- package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextInput.svelte +20 -37
- package/dist/components/forms/TextInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextareaInput.svelte +19 -35
- package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -1
- package/dist/components/sortable/Sortable.svelte +6 -33
- package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
- package/dist/components/sortable/announce.d.ts +5 -0
- package/dist/components/sortable/announce.d.ts.map +1 -0
- package/dist/components/sortable/announce.js +33 -0
- package/dist/components/workspace/admin-shell/AdminShell.svelte +424 -58
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +27 -2
- package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellBrand.svelte +86 -0
- package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts +18 -0
- package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte +77 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts +26 -0
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +88 -16
- package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +531 -0
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +26 -0
- package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +57 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts +22 -0
- package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +290 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts +32 -0
- package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte +67 -2
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +8 -0
- package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts +67 -0
- package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout-controller.svelte.js +129 -1
- package/dist/components/workspace/admin-shell/layout.d.ts +122 -0
- package/dist/components/workspace/admin-shell/layout.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/layout.js +410 -10
- package/dist/components/workspace/admin-shell/settings.js +4 -4
- package/dist/components/workspace/admin-shell/shell-icons.d.ts +45 -0
- package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/shell-icons.js +66 -0
- package/dist/components/workspace/admin-shell/slot-labels.d.ts +33 -0
- package/dist/components/workspace/admin-shell/slot-labels.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/slot-labels.js +33 -0
- package/dist/components/workspace/admin-shell/slots.d.ts +50 -0
- package/dist/components/workspace/admin-shell/slots.d.ts.map +1 -0
- package/dist/components/workspace/admin-shell/slots.js +77 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts +35 -0
- package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/state.svelte.js +111 -0
- package/dist/components/workspace/admin-shell/types.d.ts +101 -1
- package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
- package/dist/components/workspace/index.d.ts +9 -2
- package/dist/components/workspace/index.d.ts.map +1 -1
- package/dist/components/workspace/index.js +6 -0
- package/dist/i18n/strings.workspace.d.ts +49 -0
- package/dist/i18n/strings.workspace.d.ts.map +1 -1
- package/dist/i18n/strings.workspace.js +49 -0
- package/package.json +30 -19
- package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts +0 -51
- package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts.map +0 -1
- package/dist/browser-ai/adapters/stt/whisper-wasm.js +0 -380
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import { type BottomBarMode } from './mobile-shell.js';
|
|
3
3
|
import { type ShellState } from './state.svelte.js';
|
|
4
|
-
import
|
|
4
|
+
import { type ShellSlot } from './slots.js';
|
|
5
|
+
import type { AdminShellPhoneOptions, AdminShellProps, ShellLayoutEditSurface, ShellFocusTool, ShellViewport } from './types.js';
|
|
5
6
|
interface Props extends AdminShellProps {
|
|
6
7
|
/** Pre-configured shell state. Creates one from config if omitted. */
|
|
7
8
|
state?: ShellState;
|
|
@@ -17,6 +18,30 @@ interface Props extends AdminShellProps {
|
|
|
17
18
|
tenantRailFooter?: Snippet;
|
|
18
19
|
/** Content for the left tenant panel. */
|
|
19
20
|
tenantPanel?: Snippet;
|
|
21
|
+
/**
|
|
22
|
+
* Host content for the region slots (`header.start|center|end`,
|
|
23
|
+
* `footer.start|center|end`, `leftSidebar.header|footer`,
|
|
24
|
+
* `rightSidebar.header|footer`). A slot whose region is not visible moves
|
|
25
|
+
* along its documented fallback chain (see `slotFallbackChain`).
|
|
26
|
+
*/
|
|
27
|
+
slots?: Partial<Record<ShellSlot, Snippet>>;
|
|
28
|
+
/**
|
|
29
|
+
* In-place layout editing (`AppShell` supplies it): while `active`,
|
|
30
|
+
* slots render as drop zones and hidden regions as strips.
|
|
31
|
+
*/
|
|
32
|
+
layoutEdit?: ShellLayoutEditSurface;
|
|
33
|
+
/** The shell's root element (bindable), e.g. to confine drag hit-testing. */
|
|
34
|
+
rootElement?: HTMLElement;
|
|
35
|
+
/**
|
|
36
|
+
* Room kept clear for a floating control (AppShell's floating layout
|
|
37
|
+
* toggle): CSS lengths for the header's end, the right sidebar's top and
|
|
38
|
+
* main's top. Part of the root's style so re-renders never drop it.
|
|
39
|
+
*/
|
|
40
|
+
floatingReserve?: {
|
|
41
|
+
inline?: string;
|
|
42
|
+
block?: string;
|
|
43
|
+
main?: string;
|
|
44
|
+
};
|
|
20
45
|
/** Content for the tenant panel footer. */
|
|
21
46
|
tenantFooter?: Snippet;
|
|
22
47
|
/** Content for the right focus rail. */
|
|
@@ -89,7 +114,7 @@ interface Props extends AdminShellProps {
|
|
|
89
114
|
path?: string;
|
|
90
115
|
children: Snippet;
|
|
91
116
|
}
|
|
92
|
-
declare const AdminShell: import("svelte").Component<Props, {}, "">;
|
|
117
|
+
declare const AdminShell: import("svelte").Component<Props, {}, "rootElement">;
|
|
93
118
|
type AdminShell = ReturnType<typeof AdminShell>;
|
|
94
119
|
export default AdminShell;
|
|
95
120
|
//# sourceMappingURL=AdminShell.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminShell.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/AdminShell.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminShell.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/AdminShell.svelte.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The shell brand: logo, title, subtitle and an optional home link. Rendered
|
|
4
|
+
* by `AdminShell` in its top band, or by `AppShell` as the movable
|
|
5
|
+
* `item:brand` slot item (default slot `header.start`).
|
|
6
|
+
*/
|
|
7
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
8
|
+
import type { Snippet } from 'svelte';
|
|
9
|
+
import { M } from '../../../i18n/strings.workspace.js';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
title?: string;
|
|
13
|
+
subtitle?: string;
|
|
14
|
+
homeHref?: string;
|
|
15
|
+
logoSrc?: string;
|
|
16
|
+
logoAlt?: string;
|
|
17
|
+
/** Custom brand content, receiving whether it is in the compact rail. */
|
|
18
|
+
brand?: Snippet<[{ compact: boolean }]>;
|
|
19
|
+
/** Compact (rail) form: logo or the title's first letter. */
|
|
20
|
+
compact?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
title = 'SMRT',
|
|
25
|
+
subtitle = '',
|
|
26
|
+
homeHref,
|
|
27
|
+
logoSrc,
|
|
28
|
+
logoAlt = '',
|
|
29
|
+
brand,
|
|
30
|
+
compact = false,
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
const { t } = useI18n();
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#snippet content()}
|
|
36
|
+
{#if brand}
|
|
37
|
+
{@render brand({ compact })}
|
|
38
|
+
{:else}
|
|
39
|
+
{#if logoSrc}<img class="smrt-admin-shell__logo" src={logoSrc} alt={logoAlt} />{/if}
|
|
40
|
+
{#if compact}
|
|
41
|
+
{#if !logoSrc}<span aria-hidden="true">{title.charAt(0)}</span>{/if}
|
|
42
|
+
{:else}
|
|
43
|
+
<div class="smrt-admin-shell__brand-text" class:wordmark={Boolean(logoSrc) && !subtitle}><strong>{title}</strong>{#if subtitle}<span>{subtitle}</span>{/if}</div>
|
|
44
|
+
{/if}
|
|
45
|
+
{/if}
|
|
46
|
+
{/snippet}
|
|
47
|
+
|
|
48
|
+
{#if homeHref}
|
|
49
|
+
<a class="smrt-admin-shell__brand smrt-admin-shell__brand-link" class:compact href={homeHref} aria-label={title || t(M['ui.admin_shell.home'])}>
|
|
50
|
+
{@render content()}
|
|
51
|
+
</a>
|
|
52
|
+
{:else}
|
|
53
|
+
<div class="smrt-admin-shell__brand" class:compact>{@render content()}</div>
|
|
54
|
+
{/if}
|
|
55
|
+
|
|
56
|
+
<style>
|
|
57
|
+
.smrt-admin-shell__brand {
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: var(--smrt-spacing-2);
|
|
61
|
+
min-width: 0;
|
|
62
|
+
color: inherit;
|
|
63
|
+
text-decoration: none;
|
|
64
|
+
}
|
|
65
|
+
.smrt-admin-shell__brand-text { display: grid; min-width: 0; }
|
|
66
|
+
.smrt-admin-shell__brand.compact { justify-content: center; margin-block-end: var(--smrt-spacing-2); }
|
|
67
|
+
.smrt-admin-shell__brand-link:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 2px; }
|
|
68
|
+
.smrt-admin-shell__logo { inline-size: 2rem; block-size: 2rem; object-fit: contain; flex-shrink: 0; }
|
|
69
|
+
|
|
70
|
+
.smrt-admin-shell__brand strong,
|
|
71
|
+
.smrt-admin-shell__brand span {
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
text-overflow: ellipsis;
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.smrt-admin-shell__brand span {
|
|
78
|
+
color: var(--smrt-color-on-surface-variant);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Logo and title alone ([logo] Planner): the title reads as a wordmark,
|
|
82
|
+
its line as tall as the 2rem logo. */
|
|
83
|
+
.smrt-admin-shell__brand-text.wordmark strong {
|
|
84
|
+
font: var(--smrt-typography-headline-small-font, 500 1.5rem/2rem sans-serif);
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
title?: string;
|
|
4
|
+
subtitle?: string;
|
|
5
|
+
homeHref?: string;
|
|
6
|
+
logoSrc?: string;
|
|
7
|
+
logoAlt?: string;
|
|
8
|
+
/** Custom brand content, receiving whether it is in the compact rail. */
|
|
9
|
+
brand?: Snippet<[{
|
|
10
|
+
compact: boolean;
|
|
11
|
+
}]>;
|
|
12
|
+
/** Compact (rail) form: logo or the title's first letter. */
|
|
13
|
+
compact?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare const ShellBrand: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type ShellBrand = ReturnType<typeof ShellBrand>;
|
|
17
|
+
export default ShellBrand;
|
|
18
|
+
//# sourceMappingURL=ShellBrand.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShellBrand.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/ShellBrand.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,CAAC;IACxC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6CD,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Icon-only button used by the layout-editing chrome: a labelled `<button>`
|
|
4
|
+
* with the label as tooltip, `aria-pressed` for toggles, and a 2rem hit area
|
|
5
|
+
* (the same visual language as a nav row's `action`).
|
|
6
|
+
*/
|
|
7
|
+
import type { Snippet } from 'svelte';
|
|
8
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
9
|
+
import { SHELL_ICON_PATHS, type ShellIconName } from './shell-icons.js';
|
|
10
|
+
|
|
11
|
+
interface Props
|
|
12
|
+
extends Omit<HTMLButtonAttributes, 'aria-label' | 'title' | 'children'> {
|
|
13
|
+
/** Accessible name and tooltip. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Which filled icon to draw (omit when passing `children`). */
|
|
16
|
+
icon?: ShellIconName;
|
|
17
|
+
/** Custom icon content, drawn instead of `icon` (decorative). */
|
|
18
|
+
children?: Snippet;
|
|
19
|
+
/** Toggle state; omit for a plain action button. */
|
|
20
|
+
pressed?: boolean;
|
|
21
|
+
/** Tooltip text when it should differ from the label (default: the label). */
|
|
22
|
+
tooltip?: string;
|
|
23
|
+
/** Icon edge length in pixels (default 18). */
|
|
24
|
+
size?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let {
|
|
28
|
+
label,
|
|
29
|
+
icon,
|
|
30
|
+
children,
|
|
31
|
+
pressed,
|
|
32
|
+
tooltip,
|
|
33
|
+
size = 18,
|
|
34
|
+
type = 'button',
|
|
35
|
+
class: className = '',
|
|
36
|
+
...rest
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<!-- raw-primitive-allow: icon-only shell chrome control (tooltip + aria-pressed) -->
|
|
41
|
+
<button
|
|
42
|
+
{...rest}
|
|
43
|
+
{type}
|
|
44
|
+
class="smrt-shell-icon-button {className}"
|
|
45
|
+
aria-label={label}
|
|
46
|
+
title={tooltip ?? label}
|
|
47
|
+
aria-pressed={pressed}
|
|
48
|
+
>
|
|
49
|
+
{#if children}
|
|
50
|
+
{@render children()}
|
|
51
|
+
{:else if icon}
|
|
52
|
+
<svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" aria-hidden="true" focusable="false">
|
|
53
|
+
<path d={SHELL_ICON_PATHS[icon]} />
|
|
54
|
+
</svg>
|
|
55
|
+
{/if}
|
|
56
|
+
</button>
|
|
57
|
+
|
|
58
|
+
<style>
|
|
59
|
+
.smrt-shell-icon-button {
|
|
60
|
+
flex: 0 0 auto;
|
|
61
|
+
display: inline-grid;
|
|
62
|
+
place-items: center;
|
|
63
|
+
box-sizing: border-box;
|
|
64
|
+
inline-size: max(2rem, var(--smrt-control-target-min, 0px));
|
|
65
|
+
block-size: max(2rem, var(--smrt-control-target-min, 0px));
|
|
66
|
+
padding: 0;
|
|
67
|
+
border: 0;
|
|
68
|
+
border-radius: var(--smrt-radius-medium, 0.5rem);
|
|
69
|
+
background: transparent;
|
|
70
|
+
color: var(--smrt-color-on-surface-variant);
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
}
|
|
73
|
+
.smrt-shell-icon-button:hover { background: var(--smrt-color-surface-container-high); color: var(--smrt-color-on-surface); }
|
|
74
|
+
.smrt-shell-icon-button[aria-pressed='true'] { color: var(--smrt-color-on-surface); }
|
|
75
|
+
.smrt-shell-icon-button:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 2px; }
|
|
76
|
+
.smrt-shell-icon-button:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon-only button used by the layout-editing chrome: a labelled `<button>`
|
|
3
|
+
* with the label as tooltip, `aria-pressed` for toggles, and a 2rem hit area
|
|
4
|
+
* (the same visual language as a nav row's `action`).
|
|
5
|
+
*/
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
8
|
+
import { type ShellIconName } from './shell-icons.js';
|
|
9
|
+
interface Props extends Omit<HTMLButtonAttributes, 'aria-label' | 'title' | 'children'> {
|
|
10
|
+
/** Accessible name and tooltip. */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Which filled icon to draw (omit when passing `children`). */
|
|
13
|
+
icon?: ShellIconName;
|
|
14
|
+
/** Custom icon content, drawn instead of `icon` (decorative). */
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
/** Toggle state; omit for a plain action button. */
|
|
17
|
+
pressed?: boolean;
|
|
18
|
+
/** Tooltip text when it should differ from the label (default: the label). */
|
|
19
|
+
tooltip?: string;
|
|
20
|
+
/** Icon edge length in pixels (default 18). */
|
|
21
|
+
size?: number;
|
|
22
|
+
}
|
|
23
|
+
declare const ShellIconButton: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type ShellIconButton = ReturnType<typeof ShellIconButton>;
|
|
25
|
+
export default ShellIconButton;
|
|
26
|
+
//# sourceMappingURL=ShellIconButton.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShellIconButton.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/ShellIconButton.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGxE,UAAU,KACR,SAAQ,IAAI,CAAC,oBAAoB,EAAE,YAAY,GAAG,OAAO,GAAG,UAAU,CAAC;IACvE,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAoCD,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Switch } from '@happyvertical/smrt-ui/forms';
|
|
2
|
+
import { Input, Switch } from '@happyvertical/smrt-ui/forms';
|
|
3
3
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
4
4
|
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
5
|
-
import { type Component, untrack } from 'svelte';
|
|
5
|
+
import { type Component, tick, untrack } from 'svelte';
|
|
6
6
|
import { M } from '../../../i18n/strings.workspace.js';
|
|
7
7
|
import Sortable from '../../sortable/Sortable.svelte';
|
|
8
8
|
import type {
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
} from '../../sortable/types.js';
|
|
14
14
|
import { useShellLayout } from './layout-context.js';
|
|
15
15
|
import type { ShellLayoutController } from './layout-controller.svelte.js';
|
|
16
|
+
import ShellIconButton from './ShellIconButton.svelte';
|
|
16
17
|
import TenantNav from './TenantNav.svelte';
|
|
17
18
|
|
|
18
19
|
interface Props {
|
|
@@ -38,6 +39,9 @@ const applied = $derived(layout.applied);
|
|
|
38
39
|
interface NavContainer extends SortableContainer {
|
|
39
40
|
hidden: boolean;
|
|
40
41
|
root: boolean;
|
|
42
|
+
custom: boolean;
|
|
43
|
+
titleVisible: boolean;
|
|
44
|
+
count: number;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
const containers = $derived<NavContainer[]>(
|
|
@@ -47,6 +51,9 @@ const containers = $derived<NavContainer[]>(
|
|
|
47
51
|
fixed: section.group === null,
|
|
48
52
|
root: section.group === null,
|
|
49
53
|
hidden: section.hidden,
|
|
54
|
+
custom: section.custom,
|
|
55
|
+
titleVisible: section.titleVisible,
|
|
56
|
+
count: section.items.length,
|
|
50
57
|
})),
|
|
51
58
|
);
|
|
52
59
|
const items = $derived<SortableItem[]>(
|
|
@@ -54,7 +61,7 @@ const items = $derived<SortableItem[]>(
|
|
|
54
61
|
section.items.map((entry) => ({
|
|
55
62
|
id: entry.id,
|
|
56
63
|
containerId: section.id,
|
|
57
|
-
label: entry.
|
|
64
|
+
label: entry.label,
|
|
58
65
|
})),
|
|
59
66
|
),
|
|
60
67
|
);
|
|
@@ -64,6 +71,40 @@ function setShown(id: string, shown: boolean): void {
|
|
|
64
71
|
else layout.hide(id);
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
let rootEl: HTMLElement | undefined = $state();
|
|
75
|
+
|
|
76
|
+
function rename(id: string, event: Event): void {
|
|
77
|
+
const input = event.currentTarget as HTMLInputElement;
|
|
78
|
+
layout.renameSection(id, input.value);
|
|
79
|
+
// Blank or rejected input snaps back to the section's real name.
|
|
80
|
+
input.value = containers.find((entry) => entry.id === id)?.label ?? '';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function createSection(): Promise<void> {
|
|
84
|
+
const id = layout.createSection(
|
|
85
|
+
t(M['ui.shell_layout_editor.new_section_label']),
|
|
86
|
+
);
|
|
87
|
+
if (!id) return;
|
|
88
|
+
await tick();
|
|
89
|
+
const input = rootEl?.querySelector<HTMLInputElement>(
|
|
90
|
+
`input[data-section-name="${CSS.escape(id)}"]`,
|
|
91
|
+
);
|
|
92
|
+
input?.focus();
|
|
93
|
+
input?.select();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function deleteSection(id: string, label: string, count: number): void {
|
|
97
|
+
if (
|
|
98
|
+
count > 0 &&
|
|
99
|
+
!globalThis.confirm?.(
|
|
100
|
+
t(M['ui.shell_layout_editor.delete_confirm'], { label }),
|
|
101
|
+
)
|
|
102
|
+
) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
layout.deleteSection(id);
|
|
106
|
+
}
|
|
107
|
+
|
|
67
108
|
function onmove(move: SortableItemMove<SortableItem, NavContainer>): void {
|
|
68
109
|
layout.moveItem(move.item.id, move.target.containerId, move.target.index);
|
|
69
110
|
}
|
|
@@ -73,7 +114,7 @@ function oncontainermove(move: SortableContainerMove<NavContainer>): void {
|
|
|
73
114
|
}
|
|
74
115
|
</script>
|
|
75
116
|
|
|
76
|
-
<section class="smrt-shell-layout-editor" aria-labelledby={headingId}>
|
|
117
|
+
<section class="smrt-shell-layout-editor" aria-labelledby={headingId} bind:this={rootEl}>
|
|
77
118
|
<header>
|
|
78
119
|
<div>
|
|
79
120
|
<h2 id={headingId}>{t(M['ui.shell_layout_editor.heading'])}</h2>
|
|
@@ -122,7 +163,12 @@ function oncontainermove(move: SortableContainerMove<NavContainer>): void {
|
|
|
122
163
|
|
|
123
164
|
<div class="smrt-shell-layout-editor__body">
|
|
124
165
|
<div class="smrt-shell-layout-editor__nav">
|
|
125
|
-
<
|
|
166
|
+
<div class="smrt-shell-layout-editor__nav-head">
|
|
167
|
+
<h3>{t(M['ui.shell_layout_editor.navigation'])}</h3>
|
|
168
|
+
<Button variant="secondary" size="sm" onclick={createSection}>
|
|
169
|
+
{t(M['ui.shell_layout_editor.new_section'])}
|
|
170
|
+
</Button>
|
|
171
|
+
</div>
|
|
126
172
|
<Sortable
|
|
127
173
|
{containers}
|
|
128
174
|
{items}
|
|
@@ -133,24 +179,46 @@ function oncontainermove(move: SortableContainerMove<NavContainer>): void {
|
|
|
133
179
|
>
|
|
134
180
|
{#snippet containerHeader({ container })}
|
|
135
181
|
{@const entry = containers.find((candidate) => candidate.id === container.id)}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
182
|
+
{#if entry?.root}
|
|
183
|
+
<strong>{container.label}</strong>
|
|
184
|
+
{:else}
|
|
185
|
+
<Input
|
|
186
|
+
class="smrt-shell-layout-editor__name"
|
|
139
187
|
interaction={false}
|
|
140
|
-
|
|
141
|
-
aria-label={t(M['ui.shell_layout_editor.
|
|
142
|
-
|
|
188
|
+
data-section-name={container.id}
|
|
189
|
+
aria-label={t(M['ui.shell_layout_editor.section_name'], { label: container.label })}
|
|
190
|
+
value={container.label}
|
|
191
|
+
onchange={(event) => rename(container.id, event)}
|
|
192
|
+
/>
|
|
193
|
+
<ShellIconButton
|
|
194
|
+
icon={entry?.hidden ? 'eyeOff' : 'eye'}
|
|
195
|
+
pressed={!entry?.hidden}
|
|
196
|
+
label={t(M['ui.shell_layout_editor.show_entry'], { label: container.label })}
|
|
197
|
+
onclick={() => setShown(container.id, !!entry?.hidden)}
|
|
143
198
|
/>
|
|
199
|
+
<ShellIconButton
|
|
200
|
+
icon={entry?.titleVisible === false ? 'headingOff' : 'heading'}
|
|
201
|
+
pressed={entry?.titleVisible ?? true}
|
|
202
|
+
label={t(M['ui.shell_layout_editor.show_title_for'], { label: container.label })}
|
|
203
|
+
onclick={() => layout.setSectionTitleVisible(container.id, !(entry?.titleVisible ?? true))}
|
|
204
|
+
/>
|
|
205
|
+
{#if entry?.custom}
|
|
206
|
+
<ShellIconButton
|
|
207
|
+
icon="trash"
|
|
208
|
+
label={t(M['ui.shell_layout_editor.delete_section'], { label: container.label })}
|
|
209
|
+
onclick={() => deleteSection(container.id, container.label, entry.count)}
|
|
210
|
+
/>
|
|
211
|
+
{/if}
|
|
144
212
|
{/if}
|
|
145
213
|
{/snippet}
|
|
146
214
|
{#snippet item({ item: entry, container })}
|
|
147
215
|
{@const hidden = layout.isHidden(entry.id)}
|
|
148
216
|
<span class="smrt-shell-layout-editor__label" class:smrt-shell-layout-editor__muted={hidden || layout.isHidden(container.id)}>{entry.label}</span>
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
217
|
+
<ShellIconButton
|
|
218
|
+
icon={hidden ? 'eyeOff' : 'eye'}
|
|
219
|
+
pressed={!hidden}
|
|
220
|
+
label={t(M['ui.shell_layout_editor.show_entry'], { label: entry.label })}
|
|
221
|
+
onclick={() => setShown(entry.id, hidden)}
|
|
154
222
|
/>
|
|
155
223
|
{/snippet}
|
|
156
224
|
</Sortable>
|
|
@@ -187,8 +255,12 @@ function oncontainermove(move: SortableContainerMove<NavContainer>): void {
|
|
|
187
255
|
.smrt-shell-layout-editor__panels legend { padding-inline: var(--smrt-spacing-1); font: var(--smrt-typography-title-small-font); }
|
|
188
256
|
.smrt-shell-layout-editor__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--smrt-spacing-4); }
|
|
189
257
|
.smrt-shell-layout-editor__body { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--smrt-spacing-4); align-items: start; }
|
|
258
|
+
.smrt-shell-layout-editor__nav-head { display: flex; align-items: center; justify-content: space-between; gap: var(--smrt-spacing-3); }
|
|
259
|
+
.smrt-shell-layout-editor__nav-head h3 { margin-block-end: 0; }
|
|
260
|
+
:global(.smrt-shell-layout-editor__name) { flex: 1 1 8rem; min-inline-size: 0; }
|
|
190
261
|
.smrt-shell-layout-editor__label { flex: 1 1 auto; min-inline-size: 0; }
|
|
191
262
|
.smrt-shell-layout-editor__preview-frame { padding: var(--smrt-spacing-3); border: 1px dashed var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-md); background: var(--smrt-color-surface-container-low, var(--smrt-color-surface)); }
|
|
263
|
+
/* Label on its own line (never broken mid-word); the select and Reset share the next line. */
|
|
192
264
|
@media (max-width: 48rem) {
|
|
193
265
|
.smrt-shell-layout-editor header { flex-direction: column; }
|
|
194
266
|
.smrt-shell-layout-editor__body { grid-template-columns: minmax(0, 1fr); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShellLayoutEditor.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/ShellLayoutEditor.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"ShellLayoutEditor.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/admin-shell/ShellLayoutEditor.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,QAAQ,CAAC;AAUvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAK3E,UAAU,KAAK;IACb,oEAAoE;IACpE,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,aAAa,CAAC,EAAE,SAAS,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAqLD,QAAA,MAAM,iBAAiB,0BAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|