@fayz-ai/ui 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ChartWidgetInner-GDE5PBTR.js → ChartWidgetInner-IOLIUYTB.js} +21 -8
- package/dist/ChartWidgetInner-IOLIUYTB.js.map +1 -0
- package/dist/analytics/AnalyticsCard.d.ts.map +1 -1
- package/dist/analytics/AnalyticsControls.d.ts.map +1 -1
- package/dist/analytics/context.d.ts +15 -1
- package/dist/analytics/context.d.ts.map +1 -1
- package/dist/analytics/index.d.ts +1 -1
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/chunk-3OVZ5JJQ.js +540 -0
- package/dist/chunk-3OVZ5JJQ.js.map +1 -0
- package/dist/{chunk-UZYXFEQS.js → chunk-4GK6IHOI.js} +16 -3
- package/dist/chunk-4GK6IHOI.js.map +1 -0
- package/dist/{chunk-46UZAKFJ.js → chunk-5VF45NLE.js} +7 -6
- package/dist/chunk-5VF45NLE.js.map +1 -0
- package/dist/{chunk-5KAGNW45.js → chunk-6BJTH3L6.js} +5 -5
- package/dist/chunk-6BJTH3L6.js.map +1 -0
- package/dist/chunk-AASANYXN.js +601 -0
- package/dist/chunk-AASANYXN.js.map +1 -0
- package/dist/{chunk-2EFRFYGF.js → chunk-E44WOPCR.js} +198 -39
- package/dist/chunk-E44WOPCR.js.map +1 -0
- package/dist/chunk-HKGTF2YA.js +117 -0
- package/dist/chunk-HKGTF2YA.js.map +1 -0
- package/dist/chunk-OKZ6WQB3.js +57 -0
- package/dist/chunk-OKZ6WQB3.js.map +1 -0
- package/dist/{chunk-MVH64JFG.js → chunk-PZU7XC2M.js} +780 -719
- package/dist/chunk-PZU7XC2M.js.map +1 -0
- package/dist/{chunk-77CUIMOI.js → chunk-SDPYDWWV.js} +459 -226
- package/dist/chunk-SDPYDWWV.js.map +1 -0
- package/dist/dashboard/ChartWidgetInner.d.ts.map +1 -1
- package/dist/dashboard/index.js +5 -4
- package/dist/hooks/useIsWide.d.ts +16 -0
- package/dist/hooks/useIsWide.d.ts.map +1 -0
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -17
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.d.ts +31 -3
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/ModulePage.d.ts +4 -0
- package/dist/layout/ModulePage.d.ts.map +1 -1
- package/dist/layout/SaveBar.d.ts.map +1 -1
- package/dist/layout/Sidebar.d.ts +27 -4
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Topbar.d.ts +14 -3
- package/dist/layout/Topbar.d.ts.map +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +5 -4
- package/dist/primitives/SearchCombobox.d.ts +9 -1
- package/dist/primitives/SearchCombobox.d.ts.map +1 -1
- package/dist/primitives/checkbox.d.ts +4 -0
- package/dist/primitives/checkbox.d.ts.map +1 -1
- package/dist/primitives/color-palette.d.ts +24 -0
- package/dist/primitives/color-palette.d.ts.map +1 -0
- package/dist/primitives/header-tabs.d.ts +11 -1
- package/dist/primitives/header-tabs.d.ts.map +1 -1
- package/dist/primitives/image-drop.d.ts +28 -0
- package/dist/primitives/image-drop.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +11 -3
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +7 -5
- package/dist/primitives/list-view.d.ts +11 -1
- package/dist/primitives/list-view.d.ts.map +1 -1
- package/dist/primitives/modal.d.ts.map +1 -1
- package/dist/primitives/option-select.d.ts +46 -0
- package/dist/primitives/option-select.d.ts.map +1 -0
- package/dist/primitives/page-actions.d.ts +55 -0
- package/dist/primitives/page-actions.d.ts.map +1 -0
- package/dist/primitives/page-header.d.ts +5 -2
- package/dist/primitives/page-header.d.ts.map +1 -1
- package/dist/primitives/page-toolbar.d.ts +20 -1
- package/dist/primitives/page-toolbar.d.ts.map +1 -1
- package/dist/primitives/refresh-button.d.ts.map +1 -1
- package/dist/primitives/row-actions.d.ts +11 -0
- package/dist/primitives/row-actions.d.ts.map +1 -0
- package/dist/primitives/sheet.d.ts.map +1 -1
- package/dist/primitives/step-progress.d.ts +20 -0
- package/dist/primitives/step-progress.d.ts.map +1 -0
- package/dist/primitives/use-row-selection.d.ts +50 -0
- package/dist/primitives/use-row-selection.d.ts.map +1 -0
- package/dist/primitives/whatsapp-icon.d.ts +7 -0
- package/dist/primitives/whatsapp-icon.d.ts.map +1 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/layout.store.d.ts +1 -0
- package/dist/stores/layout.store.d.ts.map +1 -1
- package/dist/stores/page-header.store.d.ts +39 -5
- package/dist/stores/page-header.store.d.ts.map +1 -1
- package/dist/styles.css +186 -3
- package/dist/wizard/Wizard.d.ts +38 -0
- package/dist/wizard/Wizard.d.ts.map +1 -0
- package/dist/wizard/WizardField.d.ts +22 -0
- package/dist/wizard/WizardField.d.ts.map +1 -0
- package/dist/wizard/index.d.ts +6 -0
- package/dist/wizard/index.d.ts.map +1 -0
- package/dist/wizard/index.js +5 -0
- package/dist/wizard/index.js.map +1 -0
- package/dist/wizard/logic.d.ts +39 -0
- package/dist/wizard/logic.d.ts.map +1 -0
- package/dist/wizard/types.d.ts +95 -0
- package/dist/wizard/types.d.ts.map +1 -0
- package/dist/wizard/useWizard.d.ts +47 -0
- package/dist/wizard/useWizard.d.ts.map +1 -0
- package/package.json +12 -6
- package/dist/ChartWidgetInner-GDE5PBTR.js.map +0 -1
- package/dist/chunk-2EFRFYGF.js.map +0 -1
- package/dist/chunk-46UZAKFJ.js.map +0 -1
- package/dist/chunk-5KAGNW45.js.map +0 -1
- package/dist/chunk-77CUIMOI.js.map +0 -1
- package/dist/chunk-LFZFBN3P.js +0 -142
- package/dist/chunk-LFZFBN3P.js.map +0 -1
- package/dist/chunk-MVH64JFG.js.map +0 -1
- package/dist/chunk-UZYXFEQS.js.map +0 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type PageActionIntent = 'primary' | 'secondary' | 'utility' | 'danger';
|
|
3
|
+
export interface PageActionItem {
|
|
4
|
+
id: string;
|
|
5
|
+
/** Already translated. The point of the type is that nothing hardcodes here. */
|
|
6
|
+
label: string;
|
|
7
|
+
icon?: React.ComponentType<{
|
|
8
|
+
className?: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* - `primary` the one thing the screen is for. At most one; extras demote.
|
|
12
|
+
* - `secondary` other ways to do it (import, from AI) — folded under primary.
|
|
13
|
+
* - `utility` settings, export, refresh. Icon-only beside the primary.
|
|
14
|
+
* - `danger` destructive. Never inline; always behind the overflow.
|
|
15
|
+
*/
|
|
16
|
+
intent?: PageActionIntent;
|
|
17
|
+
onSelect: () => void | Promise<void>;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Set by whoever resolves permissions — this renderer has no access engine. */
|
|
20
|
+
hidden?: boolean;
|
|
21
|
+
/** Long-form line under the label when the action opens in a menu. */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Kept so converting a hand-written button does not silently drop its hook. */
|
|
24
|
+
testId?: string;
|
|
25
|
+
/**
|
|
26
|
+
* This action makes a NEW record. It decides the FAB's face: "+" on a screen
|
|
27
|
+
* you add to, "⋮" on a record you act upon. Not derivable from the icon —
|
|
28
|
+
* "Novo produto" carries a Package, not a plus — and not from the screen
|
|
29
|
+
* either, since a settings tab has a back crumb and still adds. Defaults to
|
|
30
|
+
* the icon being a plus, which covers the plainly-named cases.
|
|
31
|
+
*/
|
|
32
|
+
creates?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Offered on a pointer device only. Some actions cannot be FINISHED on a
|
|
35
|
+
* phone — picking a CSV off a filesystem and mapping its columns is the
|
|
36
|
+
* clearest case — and a menu entry that leads nowhere is worse than one that
|
|
37
|
+
* is absent. Not about screen width: about whether the job can be done.
|
|
38
|
+
*/
|
|
39
|
+
desktopOnly?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Renders a declared action set.
|
|
43
|
+
*
|
|
44
|
+
* One primary survives: a screen with three equal buttons is a screen with no
|
|
45
|
+
* obvious next step, and on a phone it simply overflows the header. Anything
|
|
46
|
+
* after the first primary is treated as secondary.
|
|
47
|
+
*/
|
|
48
|
+
export declare function PageActionBar({ actions, className }: {
|
|
49
|
+
actions: PageActionItem[];
|
|
50
|
+
className?: string;
|
|
51
|
+
}): React.JSX.Element | null;
|
|
52
|
+
/** The FAB's accessible name when it opens a menu. Overridable for locale. */
|
|
53
|
+
export declare let actionsMenuLabel: string;
|
|
54
|
+
export declare function setActionsMenuLabel(label: string): void;
|
|
55
|
+
//# sourceMappingURL=page-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-actions.d.ts","sourceRoot":"","sources":["../../src/primitives/page-actions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA0B9B,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gFAAgF;IAChF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAOD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,4BA4FtG;AAmMD,8EAA8E;AAC9E,eAAO,IAAI,gBAAgB,QAAU,CAAA;AACrC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,QAA8B"}
|
|
@@ -4,10 +4,13 @@ import * as React from 'react';
|
|
|
4
4
|
* title comes from the route instead of the page. Two copies of this markup is
|
|
5
5
|
* how the app grew two different back arrows.
|
|
6
6
|
*/
|
|
7
|
-
export declare function PageHeaderCrumb({ title, parentLabel, onBack, }: {
|
|
7
|
+
export declare function PageHeaderCrumb({ title, parentLabel, onBack, headingLevel, }: {
|
|
8
8
|
title?: React.ReactNode;
|
|
9
9
|
parentLabel?: string;
|
|
10
10
|
onBack?: () => void;
|
|
11
|
+
/** The shell passes 'h1': its page title IS the page's top-level heading, and
|
|
12
|
+
* most screens render no other one, so h2 there is a skipped level. */
|
|
13
|
+
headingLevel?: 'h1' | 'h2';
|
|
11
14
|
}): React.JSX.Element | null;
|
|
12
15
|
export interface PageHeaderProps {
|
|
13
16
|
/** What THIS page is. Empty while loading → pulsing placeholder. */
|
|
@@ -19,5 +22,5 @@ export interface PageHeaderProps {
|
|
|
19
22
|
/** Link text when there is no `parentLabel`. */
|
|
20
23
|
backLabel?: string;
|
|
21
24
|
}
|
|
22
|
-
export declare function PageHeader({ title, onBack, parentLabel, backLabel }: PageHeaderProps): React.JSX.Element
|
|
25
|
+
export declare function PageHeader({ title, onBack, parentLabel, backLabel }: PageHeaderProps): React.JSX.Element;
|
|
23
26
|
//# sourceMappingURL=page-header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../../src/primitives/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAsB9B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,WAAW,EACX,MAAM,
|
|
1
|
+
{"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../../src/primitives/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAsB9B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,WAAW,EACX,MAAM,EACN,YAAmB,GACpB,EAAE;IACD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;4EACwE;IACxE,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAC3B,4BA8CA;AAED,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,eAAe,qBAwBpF"}
|
|
@@ -11,6 +11,19 @@ export declare const ToolbarButton: React.ForwardRefExoticComponent<Omit<import(
|
|
|
11
11
|
icon?: React.ElementType;
|
|
12
12
|
caret?: boolean;
|
|
13
13
|
}, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
14
|
+
/**
|
|
15
|
+
* O gatilho de COMANDO da barra — Exportar, Imprimir, Novo.
|
|
16
|
+
*
|
|
17
|
+
* Mesma matéria do ToolbarButton acima (sem contorno, sem fundo, fantasma) e
|
|
18
|
+
* sem o sublinhado tracejado: o tracejado promete "este valor se troca", e
|
|
19
|
+
* imprimir não é um valor. Eram botões contornados no meio de uma barra sem
|
|
20
|
+
* contorno nenhum — duas caixas arredondadas ao lado de três rótulos soltos,
|
|
21
|
+
* que é o desenho que faz a barra parecer duas barras.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ToolbarAction: React.ForwardRefExoticComponent<Omit<import("./button").ButtonProps & React.RefAttributes<HTMLButtonElement> & {
|
|
24
|
+
icon?: React.ElementType;
|
|
25
|
+
caret?: boolean;
|
|
26
|
+
}, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
14
27
|
export interface RangeOption {
|
|
15
28
|
value: string;
|
|
16
29
|
label: string;
|
|
@@ -55,7 +68,13 @@ export interface PageToolbarProps {
|
|
|
55
68
|
refreshLabel?: string;
|
|
56
69
|
/** Solta a barra do topo (dentro de um modal, ou ao imprimir). */
|
|
57
70
|
sticky?: boolean;
|
|
71
|
+
/** Alça de arrastar à esquerda. Desligue onde a barra não flutua sobre nada. */
|
|
72
|
+
movable?: boolean;
|
|
73
|
+
/** Separa a posição desta barra da compartilhada. Ver useToolbarOffset. */
|
|
74
|
+
storageKey?: string;
|
|
75
|
+
/** Rótulo acessível da alça. */
|
|
76
|
+
moveLabel?: string;
|
|
58
77
|
className?: string;
|
|
59
78
|
}
|
|
60
|
-
export declare function PageToolbar({ range, filters, chips, customize, actions, onRefresh, refreshLabel, sticky, className, }: PageToolbarProps): React.JSX.Element | null;
|
|
79
|
+
export declare function PageToolbar({ range, filters, chips, customize, actions, onRefresh, refreshLabel, sticky, movable, storageKey, moveLabel, className, }: PageToolbarProps): React.JSX.Element | null;
|
|
61
80
|
//# sourceMappingURL=page-toolbar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-toolbar.d.ts","sourceRoot":"","sources":["../../src/primitives/page-toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"page-toolbar.d.ts","sourceRoot":"","sources":["../../src/primitives/page-toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAsB9B;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;WAEuB,KAAK,CAAC,WAAW;YAAU,OAAO;mDAyBjF,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;WAEuB,KAAK,CAAC,WAAW;YAAU,OAAO;mDAmBjF,CAAA;AAEF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;sEACkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC,WAAW,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAe,EAAE,SAAS,GACnF,EAAE,iBAAiB,qBAwBnB;AA+ID,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oDAAoD;IACpD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,kCAAkC;IAClC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,oDAAoD;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAClE,MAAa,EAAE,OAAc,EAAE,UAAqB,EAAE,SAAS,EAAE,SAAS,GAC3E,EAAE,gBAAgB,4BAuFlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-button.d.ts","sourceRoot":"","sources":["../../src/primitives/refresh-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"refresh-button.d.ts","sourceRoot":"","sources":["../../src/primitives/refresh-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,kBAAkB,qBA2CjH;yBA3Ce,aAAa"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PageActionItem } from './page-actions';
|
|
3
|
+
export declare function RowActions({ actions, className, inlineLimit, }: {
|
|
4
|
+
actions: PageActionItem[];
|
|
5
|
+
className?: string;
|
|
6
|
+
inlineLimit?: number;
|
|
7
|
+
}): React.JSX.Element | null;
|
|
8
|
+
/** Overridable so an app in another language is not stuck with this one. */
|
|
9
|
+
export declare let rowActionsLabel: string;
|
|
10
|
+
export declare function setRowActionsLabel(label: string): void;
|
|
11
|
+
//# sourceMappingURL=row-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-actions.d.ts","sourceRoot":"","sources":["../../src/primitives/row-actions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAoBpD,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,SAAS,EACT,WAA0B,GAC3B,EAAE;IACD,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,4BAyEA;AAED,4EAA4E;AAC5E,eAAO,IAAI,eAAe,QAAU,CAAA;AACpC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,QAA6B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.d.ts","sourceRoot":"","sources":["../../src/primitives/sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AA8BzD,QAAA,MAAM,KAAK,uCAAuB,CAAA;AAClC,QAAA,MAAM,YAAY,8GAA0B,CAAA;AAC5C,QAAA,MAAM,UAAU,4GAAwB,CAAA;AACxC,QAAA,MAAM,WAAW,6CAAyB,CAAA;AAM1C,QAAA,MAAM,YAAY,8JAYhB,CAAA;AAOF,QAAA,MAAM,YAAY;IAGd,kDAAkD;YAC1C,MAAM;IACd,qCAAqC;gBACzB,OAAO;IACnB,6EAA6E;cACnE,MAAM,GAAG,KAAK,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"sheet.d.ts","sourceRoot":"","sources":["../../src/primitives/sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AA8BzD,QAAA,MAAM,KAAK,uCAAuB,CAAA;AAClC,QAAA,MAAM,YAAY,8GAA0B,CAAA;AAC5C,QAAA,MAAM,UAAU,4GAAwB,CAAA;AACxC,QAAA,MAAM,WAAW,6CAAyB,CAAA;AAM1C,QAAA,MAAM,YAAY,8JAYhB,CAAA;AAOF,QAAA,MAAM,YAAY;IAGd,kDAAkD;YAC1C,MAAM;IACd,qCAAqC;gBACzB,OAAO;IACnB,6EAA6E;cACnE,MAAM,GAAG,KAAK,GAAG,MAAM;wCAyCnC,CAAA;AAOF,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,qBAOjF;kBAPQ,WAAW;;;AAcpB,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,qBAOjF;kBAPQ,WAAW;;;AAcpB,QAAA,MAAM,UAAU,oKASd,CAAA;AAOF,QAAA,MAAM,gBAAgB,8KASpB,CAAA;AAOF,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,qBAO/E;kBAPQ,SAAS;;;AAUlB,OAAO,EACL,KAAK,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface StepProgressProps {
|
|
3
|
+
/** How many steps the flow has. */
|
|
4
|
+
total: number;
|
|
5
|
+
/** Zero-based index of the step on screen. */
|
|
6
|
+
current: number;
|
|
7
|
+
/** Jump to a step. Only offered for steps already visited. */
|
|
8
|
+
onSelect?: (index: number) => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
'aria-label'?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Segmented progress rail — one bar per step, filled up to the current one.
|
|
14
|
+
*
|
|
15
|
+
* A single continuous bar tells you how far along you are; segments also tell you
|
|
16
|
+
* how much is LEFT, which is what stops someone abandoning a form they think is
|
|
17
|
+
* endless. Sits at the bottom of the wizard column, above the footer.
|
|
18
|
+
*/
|
|
19
|
+
export declare function StepProgress({ total, current, onSelect, className, ...rest }: StepProgressProps): React.JSX.Element;
|
|
20
|
+
//# sourceMappingURL=step-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-progress.d.ts","sourceRoot":"","sources":["../../src/primitives/step-progress.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,iBAAiB,qBAiC/F"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { BulkAction } from './bulk-action-bar';
|
|
3
|
+
/**
|
|
4
|
+
* One entry in the bar that appears when rows are ticked. It receives the
|
|
5
|
+
* selected ROWS, not their ids: an action that has to go back to the store to
|
|
6
|
+
* learn what it is acting on is an action that can act on stale data.
|
|
7
|
+
*/
|
|
8
|
+
export interface RowBulkAction<T> {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
icon?: React.ComponentType<{
|
|
12
|
+
className?: string;
|
|
13
|
+
}>;
|
|
14
|
+
onSelect: (rows: T[]) => void | Promise<void>;
|
|
15
|
+
/** Red label. Reserved for what cannot be undone. */
|
|
16
|
+
destructive?: boolean;
|
|
17
|
+
/** Moves the action into the "…" menu instead of the button row. */
|
|
18
|
+
overflow?: boolean;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface UseRowSelectionOptions<T> {
|
|
22
|
+
/** The rows currently on screen — what a selection may reach. */
|
|
23
|
+
rows: T[] | null | undefined;
|
|
24
|
+
actions?: RowBulkAction<T>[];
|
|
25
|
+
/** Row identity. Defaults to `row.id`. */
|
|
26
|
+
getRowId?: (row: T) => string;
|
|
27
|
+
/** Turns checkboxes off even with actions declared (e.g. a card grid, which
|
|
28
|
+
* has no row to hang one off). */
|
|
29
|
+
enabled?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface RowSelection<T> {
|
|
32
|
+
selectedIds: string[];
|
|
33
|
+
selectedRows: T[];
|
|
34
|
+
setSelectedIds: (ids: string[]) => void;
|
|
35
|
+
clear: () => void;
|
|
36
|
+
/** Ticks every row on screen. */
|
|
37
|
+
selectAll: () => void;
|
|
38
|
+
/** Actions bound to the current selection, ready for BulkActionBar. */
|
|
39
|
+
barActions: BulkAction[];
|
|
40
|
+
/** Whether to draw the checkbox column at all. */
|
|
41
|
+
selectable: boolean;
|
|
42
|
+
/** Selection is on AND something is ticked — the bar is showing. */
|
|
43
|
+
hasSelection: boolean;
|
|
44
|
+
/** Resolved row identity, to hand back to DataTable. */
|
|
45
|
+
getRowId: (row: T) => string;
|
|
46
|
+
/** How many rows "select all" would reach. */
|
|
47
|
+
total: number;
|
|
48
|
+
}
|
|
49
|
+
export declare function useRowSelection<T>({ rows, actions, getRowId, enabled, }: UseRowSelectionOptions<T>): RowSelection<T>;
|
|
50
|
+
//# sourceMappingURL=use-row-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-row-selection.d.ts","sourceRoot":"","sources":["../../src/primitives/use-row-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AASnD;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,iEAAiE;IACjE,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,CAAA;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAC7B;uCACmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,YAAY,EAAE,CAAC,EAAE,CAAA;IACjB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,iCAAiC;IACjC,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,uEAAuE;IACvE,UAAU,EAAE,UAAU,EAAE,CAAA;IACxB,kDAAkD;IAClD,UAAU,EAAE,OAAO,CAAA;IACnB,oEAAoE;IACpE,YAAY,EAAE,OAAO,CAAA;IACrB,wDAAwD;IACxD,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAC5B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,EACjC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,OAAc,GACf,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAuD7C"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface WhatsAppIconProps extends React.SVGProps<SVGSVGElement> {
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const WHATSAPP_BRAND_COLOR = "#25D366";
|
|
6
|
+
export declare function WhatsAppIcon({ className, ...props }: WhatsAppIconProps): React.JSX.Element;
|
|
7
|
+
//# sourceMappingURL=whatsapp-icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp-icon.d.ts","sourceRoot":"","sources":["../../src/primitives/whatsapp-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,oBAAoB,YAAY,CAAA;AAE7C,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,qBAYtE"}
|
package/dist/stores/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { useLayoutStore } from './layout.store';
|
|
2
2
|
export { useThemeStore, lightTheme, darkTheme, type ThemeTokens, type SemanticColors, type UIPerceptionTokens, type CreateThemeOptions, } from './theme.store';
|
|
3
|
-
export { usePageHeader,
|
|
3
|
+
export { usePageHeader, usePageHeaderClaimed, usePageTitleSlot, PageTitlePortal, usePageHeaderStore, usePageHeaderHost, useHasPageHeaderHost, useHasPageHeaderBack, useHasPageHeaderOutlet, PageHeaderOutlet, useRegisterPageActions, useHasPageActions, } from './page-header.store';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAC1F,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,gBAAgB,EACvG,sBAAsB,EAAE,iBAAiB,GAC1C,MAAM,qBAAqB,CAAA"}
|
|
@@ -3,6 +3,7 @@ interface LayoutState {
|
|
|
3
3
|
sidebarCollapsed: boolean;
|
|
4
4
|
mobileDrawerOpen: boolean;
|
|
5
5
|
commandPaletteOpen: boolean;
|
|
6
|
+
setMobileDrawerOpen: (open: boolean) => void;
|
|
6
7
|
toggleSidebar: () => void;
|
|
7
8
|
setSidebarCollapsed: (collapsed: boolean) => void;
|
|
8
9
|
toggleMobileDrawer: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.store.d.ts","sourceRoot":"","sources":["../../src/stores/layout.store.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,OAAO,CAAA;IACzB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,mBAAmB,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IACjD,kBAAkB,EAAE,MAAM,IAAI,CAAA;IAC9B,qBAAqB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAC/C;AAED,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"layout.store.d.ts","sourceRoot":"","sources":["../../src/stores/layout.store.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,OAAO,CAAA;IACzB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,mBAAmB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC5C,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,mBAAmB,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IACjD,kBAAkB,EAAE,MAAM,IAAI,CAAA;IAC9B,qBAAqB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CAC/C;AAED,eAAO,MAAM,cAAc,0EAwBxB,CAAA"}
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
interface PageHeaderState {
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Where a page's own header DRAWS, so it can stay in the tree that wrote it.
|
|
5
|
+
*
|
|
6
|
+
* This used to be the node itself, handed over through this store — and a
|
|
7
|
+
* store is not a React tree. The shell rendered it under ITS providers, so a
|
|
8
|
+
* title carrying anything plugin-shaped (a quote's status dropdown) threw
|
|
9
|
+
* "useStore must be used within CrmPage" and took the page with it. Same
|
|
10
|
+
* lesson the right rail already learned: the page stays where it was written
|
|
11
|
+
* and portals its body in.
|
|
12
|
+
*/
|
|
13
|
+
shellSlot: HTMLElement | null;
|
|
14
|
+
setShellSlot: (element: HTMLElement | null) => void;
|
|
15
|
+
/** A container deeper than the shell — a module's own content column — that is
|
|
16
|
+
* better placed to draw the header. It wins while it is mounted. */
|
|
17
|
+
outletSlot: HTMLElement | null;
|
|
18
|
+
setOutletSlot: (element: HTMLElement | null) => void;
|
|
19
|
+
/** A page is drawing its own header, so the shell must not draw one too. */
|
|
20
|
+
claimed: boolean;
|
|
5
21
|
/** Identity of whoever owns the slot, so a late unmount can't clear a newer
|
|
6
22
|
* owner's content — the exact race you get navigating form → form. */
|
|
7
23
|
owner: string | null;
|
|
@@ -31,7 +47,7 @@ interface PageHeaderState {
|
|
|
31
47
|
* um "Novo" entregue a uma barra escondida simplesmente não aparecia.
|
|
32
48
|
*/
|
|
33
49
|
actions: number;
|
|
34
|
-
claim: (owner: string,
|
|
50
|
+
claim: (owner: string, hasBack?: boolean) => void;
|
|
35
51
|
release: (owner: string) => void;
|
|
36
52
|
addHost: () => void;
|
|
37
53
|
removeHost: () => void;
|
|
@@ -47,7 +63,12 @@ export declare function useRegisterPageActions(): void;
|
|
|
47
63
|
* elas no celular, e para não existir vazia. */
|
|
48
64
|
export declare function useHasPageActions(): boolean;
|
|
49
65
|
/** Read the current override. The shell calls this; pages should not. */
|
|
50
|
-
|
|
66
|
+
/** True while a page is drawing its own header into the bar's slot. */
|
|
67
|
+
export declare function usePageHeaderClaimed(): boolean;
|
|
68
|
+
/** The bar's portal target, for the page that draws into it. */
|
|
69
|
+
export declare function usePageTitleSlot(): HTMLElement | null;
|
|
70
|
+
/** Registers the bar's portal target. Called by the shell. */
|
|
71
|
+
export declare function usePageTitleSlotHost(): (element: HTMLElement | null) => void;
|
|
51
72
|
/**
|
|
52
73
|
* Declare that this shell renders the page-header slot. Called by the layout,
|
|
53
74
|
* never by a page. Without it `PageHeader` cannot tell "nobody claimed the bar"
|
|
@@ -83,11 +104,24 @@ export declare function PageHeaderOutlet({ className }: {
|
|
|
83
104
|
* The node is re-claimed on every change so a breadcrumb whose label depends on
|
|
84
105
|
* loaded data (a record's name) updates once it arrives.
|
|
85
106
|
*/
|
|
86
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Tells the bar that this page is drawing its own header, and whether that
|
|
109
|
+
* header carries a back action. The header ITSELF goes through `PageTitlePortal`
|
|
110
|
+
* — flags travel as data, JSX stays in the tree that wrote it.
|
|
111
|
+
*/
|
|
112
|
+
export declare function usePageHeader(active: boolean, options?: {
|
|
87
113
|
back?: boolean;
|
|
88
114
|
}): void;
|
|
89
115
|
/** True while the bar is showing a subpage's "← parent / title". See
|
|
90
116
|
* `PageHeaderState.hasBack`. */
|
|
91
117
|
export declare function useHasPageHeaderBack(): boolean;
|
|
92
118
|
export { usePageHeaderStore };
|
|
119
|
+
/**
|
|
120
|
+
* Draws a page's own header into the bar WITHOUT leaving its React tree, so a
|
|
121
|
+
* title made of plugin components still has its plugin's providers above it.
|
|
122
|
+
* With nowhere to draw into it renders where it stands, as any fallback.
|
|
123
|
+
*/
|
|
124
|
+
export declare function PageTitlePortal({ children }: {
|
|
125
|
+
children: React.ReactNode;
|
|
126
|
+
}): React.ReactElement | null;
|
|
93
127
|
//# sourceMappingURL=page-header.store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-header.store.d.ts","sourceRoot":"","sources":["../../src/stores/page-header.store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"page-header.store.d.ts","sourceRoot":"","sources":["../../src/stores/page-header.store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,UAAU,eAAe;IACvB;;;;;;;;;OASG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;IAC7B,YAAY,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IACnD;yEACqE;IACrE,UAAU,EAAE,WAAW,GAAG,IAAI,CAAA;IAC9B,aAAa,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IACpD,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB;2EACuE;IACvE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;8DAI0D;IAC1D,OAAO,EAAE,OAAO,CAAA;IAChB;;8EAE0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;OAQG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACjD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,QAAA,MAAM,kBAAkB,8EAqBrB,CAAA;AAEH,gFAAgF;AAChF,wBAAgB,sBAAsB,IAAI,IAAI,CAO7C;AAED;iDACiD;AACjD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,yEAAyE;AACzE,uEAAuE;AACvE,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,IAAI,WAAW,GAAG,IAAI,CAErD;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;+BAC+B;AAC/B,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAiBjG;AAED;;;;;;;;;;;;;;GAcG;AACH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAWjF;AAED;iCACiC;AACjC,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAItG"}
|
package/dist/styles.css
CHANGED
|
@@ -618,12 +618,33 @@ select.bg-card,
|
|
|
618
618
|
to { opacity: 0; transform: translateX(-100%); }
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
/* Command palette animation
|
|
621
|
+
/* Command palette animation.
|
|
622
|
+
The desktop card is centred with translateX(-50%), so its keyframes have to
|
|
623
|
+
carry that translate or the animation snaps it back to the left edge. On a
|
|
624
|
+
phone the palette is full-bleed and centres nothing — the same keyframes
|
|
625
|
+
dragged it half a screen off. Two animations, split at the same breakpoint
|
|
626
|
+
the layout is. */
|
|
622
627
|
.saas-cmd-palette[data-state="open"] {
|
|
623
|
-
animation: saas-cmd-in 200ms ease-out both;
|
|
628
|
+
animation: saas-cmd-in-sheet 200ms ease-out both;
|
|
624
629
|
}
|
|
625
630
|
.saas-cmd-palette[data-state="closed"] {
|
|
626
|
-
animation: saas-cmd-out 150ms ease-in both;
|
|
631
|
+
animation: saas-cmd-out-sheet 150ms ease-in both;
|
|
632
|
+
}
|
|
633
|
+
@keyframes saas-cmd-in-sheet {
|
|
634
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
635
|
+
to { opacity: 1; transform: translateY(0); }
|
|
636
|
+
}
|
|
637
|
+
@keyframes saas-cmd-out-sheet {
|
|
638
|
+
from { opacity: 1; transform: translateY(0); }
|
|
639
|
+
to { opacity: 0; transform: translateY(8px); }
|
|
640
|
+
}
|
|
641
|
+
@media (min-width: 640px) {
|
|
642
|
+
.saas-cmd-palette[data-state="open"] {
|
|
643
|
+
animation: saas-cmd-in 200ms ease-out both;
|
|
644
|
+
}
|
|
645
|
+
.saas-cmd-palette[data-state="closed"] {
|
|
646
|
+
animation: saas-cmd-out 150ms ease-in both;
|
|
647
|
+
}
|
|
627
648
|
}
|
|
628
649
|
@keyframes saas-cmd-in {
|
|
629
650
|
from { opacity: 0; transform: translateX(-50%) scale(0.96) translateY(-8px); }
|
|
@@ -651,6 +672,26 @@ select.bg-card,
|
|
|
651
672
|
to { opacity: 1; transform: translateX(0); }
|
|
652
673
|
}
|
|
653
674
|
|
|
675
|
+
/* The wizard replays these on every step, so a horizontal slide lands far more
|
|
676
|
+
often here than in normal navigation. Keep the crossfade, drop the travel. */
|
|
677
|
+
@media (prefers-reduced-motion: reduce) {
|
|
678
|
+
.saas-nav-forward,
|
|
679
|
+
.saas-nav-back {
|
|
680
|
+
animation: page-enter 150ms linear both;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/* Opacity ONLY — deliberately no transform. Used on full-screen surfaces that
|
|
685
|
+
position themselves with `fixed`: a transform on the element (or any ancestor)
|
|
686
|
+
makes it the containing block, and `fixed inset-0` stops meaning the viewport. */
|
|
687
|
+
.saas-fade-in {
|
|
688
|
+
animation: saas-fade-in 260ms var(--saas-transition-easing) both;
|
|
689
|
+
}
|
|
690
|
+
@keyframes saas-fade-in {
|
|
691
|
+
from { opacity: 0; }
|
|
692
|
+
to { opacity: 1; }
|
|
693
|
+
}
|
|
694
|
+
|
|
654
695
|
/* Sidebar rail push — when the whole left menu swaps context (e.g. app nav →
|
|
655
696
|
settings nav) the incoming rail pulls in from one side while the outgoing
|
|
656
697
|
one slides off the other, iOS-push style. The outgoing pane is absolutely
|
|
@@ -746,6 +787,18 @@ select.bg-card,
|
|
|
746
787
|
/* A field that spans the row it is on, whatever the column count is. */
|
|
747
788
|
.fz-field-wide { grid-column: 1 / -1; }
|
|
748
789
|
|
|
790
|
+
/* A required field that was empty when somebody pressed save.
|
|
791
|
+
*
|
|
792
|
+
* One rule here rather than a Tailwind string at each of the six form layouts —
|
|
793
|
+
* the marker travels with the field, and a layout added tomorrow gets it free.
|
|
794
|
+
* The ring is on the CONTROL, not the wrapper, so the label and the message
|
|
795
|
+
* either side of it stay legible. */
|
|
796
|
+
.fz-field-invalid :is(input, textarea, select, [role='combobox'], [contenteditable='true']) {
|
|
797
|
+
border-color: hsl(var(--destructive));
|
|
798
|
+
box-shadow: 0 0 0 1px hsl(var(--destructive) / 0.35);
|
|
799
|
+
}
|
|
800
|
+
.fz-field-invalid > label { color: hsl(var(--destructive)); }
|
|
801
|
+
|
|
749
802
|
/* Rows separated by a rule while they are stacked; side by side the rule is
|
|
750
803
|
drawn between unrelated neighbours, so it goes. */
|
|
751
804
|
@container (min-width: 30rem) {
|
|
@@ -793,3 +846,133 @@ select.bg-card,
|
|
|
793
846
|
@media (pointer: coarse) {
|
|
794
847
|
.fz-tap { min-height: 2.75rem; min-width: 2.75rem; }
|
|
795
848
|
}
|
|
849
|
+
|
|
850
|
+
/* ---------------------------------------------------------------------------
|
|
851
|
+
Mobile platform baseline
|
|
852
|
+
The shell renders inside Safari and Chrome on a phone, not just inside a
|
|
853
|
+
desktop viewport that happens to be narrow. These rules cover the platform
|
|
854
|
+
behaviours the browser applies on its own unless told otherwise.
|
|
855
|
+
--------------------------------------------------------------------------- */
|
|
856
|
+
|
|
857
|
+
/* Double-tap-to-zoom costs every tap a 300ms wait while the browser decides
|
|
858
|
+
whether a second tap is coming. `manipulation` opts out of that gesture and
|
|
859
|
+
keeps pinch-to-zoom, which is an accessibility guarantee we do not take away. */
|
|
860
|
+
html {
|
|
861
|
+
touch-action: manipulation;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/* iOS zooms the whole page when a field smaller than 16px takes focus, and
|
|
865
|
+
never zooms back. Anything a finger can focus gets 16px, on touch INPUT
|
|
866
|
+
rather than screen width — an iPad zooms exactly like a phone. Fields that
|
|
867
|
+
are deliberately larger keep their size. */
|
|
868
|
+
@media (pointer: coarse) {
|
|
869
|
+
input:not([type='checkbox'], [type='radio']),
|
|
870
|
+
textarea:not([hidden]),
|
|
871
|
+
select:not([hidden]) {
|
|
872
|
+
font-size: max(16px, 1em);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/* WebKit paints a grey flash over any tapped element. Suppress it and let the
|
|
877
|
+
component's own :active state be the feedback, so a tap never looks like it
|
|
878
|
+
selected a block of the page. */
|
|
879
|
+
* {
|
|
880
|
+
-webkit-tap-highlight-color: transparent;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/* A scroller that reaches its end hands the gesture to the page behind it —
|
|
884
|
+
which on mobile means a drawer, sheet or chat transcript can rubber-band the
|
|
885
|
+
whole app or trigger pull-to-refresh mid-scroll. */
|
|
886
|
+
.fz-scroll-contain {
|
|
887
|
+
overscroll-behavior: contain;
|
|
888
|
+
-webkit-overflow-scrolling: touch;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/* The notch, the Dynamic Island and the home indicator all sit inside the
|
|
892
|
+
viewport once `viewport-fit=cover` is set. Fixed chrome has to pad itself out
|
|
893
|
+
of them; env() resolves to 0 everywhere else, so these are safe on desktop. */
|
|
894
|
+
.fz-safe-b { padding-bottom: env(safe-area-inset-bottom); }
|
|
895
|
+
.fz-safe-t { padding-top: env(safe-area-inset-top); }
|
|
896
|
+
.fz-safe-x {
|
|
897
|
+
padding-left: env(safe-area-inset-left);
|
|
898
|
+
padding-right: env(safe-area-inset-right);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/* `100vh` on mobile means the viewport with the browser chrome hidden, which is
|
|
902
|
+
taller than what the user can actually see — the bottom of a vh-sized shell
|
|
903
|
+
sits under the address bar. `dvh` tracks the visible height instead; the vh
|
|
904
|
+
line stays as the fallback for browsers without it. */
|
|
905
|
+
.fz-viewport-h {
|
|
906
|
+
height: 100vh;
|
|
907
|
+
height: 100dvh;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/* How much of the bottom of the screen the tab bar owns. Anything that floats
|
|
911
|
+
above the fold — the save bar, toasts, a sheet handle — offsets by this
|
|
912
|
+
instead of hardcoding the bar's height, so it still sits right on a layout
|
|
913
|
+
that has no bar. Zero unless the shell says otherwise. */
|
|
914
|
+
:root { --fz-bottom-bar: 0px; }
|
|
915
|
+
@media (max-width: 767px) {
|
|
916
|
+
.fz-has-bottom-bar { --fz-bottom-bar: calc(4rem + env(safe-area-inset-bottom)); }
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/* ---------------------------------------------------------------------------
|
|
920
|
+
Stacking order
|
|
921
|
+
Transient surfaces have to clear the shell's own fixed chrome. The mobile
|
|
922
|
+
navigation drawer sits at 60, so a menu at the Tailwind default of 50 opens
|
|
923
|
+
BEHIND it and reads as a dead control — which is exactly what happened to the
|
|
924
|
+
tenant switcher, the user menu and notifications inside the drawer.
|
|
925
|
+
|
|
926
|
+
50 bottom tab bar
|
|
927
|
+
55 save bar (above the tab bar, below anything modal)
|
|
928
|
+
60 nav drawer, right rail
|
|
929
|
+
100 modal, sheet (covers the drawer that opened it)
|
|
930
|
+
110 dropdown, select, popover
|
|
931
|
+
120 tooltip (above a modal it is anchored inside)
|
|
932
|
+
--------------------------------------------------------------------------- */
|
|
933
|
+
|
|
934
|
+
/* ---------------------------------------------------------------------------
|
|
935
|
+
FAB speed-dial
|
|
936
|
+
A menu opening from a thumb-corner button wants to look like it came OUT of
|
|
937
|
+
that button. The shared dropdown enter (fade + 2px slide) is right for a menu
|
|
938
|
+
anchored to a toolbar and reads as instant from a 56px circle in the corner.
|
|
939
|
+
--------------------------------------------------------------------------- */
|
|
940
|
+
|
|
941
|
+
.fz-fab-menu[data-state='open'] {
|
|
942
|
+
animation: fz-fab-menu-in 220ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
943
|
+
transform-origin: bottom right;
|
|
944
|
+
}
|
|
945
|
+
.fz-fab-menu[data-state='closed'] {
|
|
946
|
+
animation: fz-fab-menu-out 130ms ease-in both;
|
|
947
|
+
transform-origin: bottom right;
|
|
948
|
+
}
|
|
949
|
+
@keyframes fz-fab-menu-in {
|
|
950
|
+
from { opacity: 0; transform: translateY(12px) scale(0.92); }
|
|
951
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
952
|
+
}
|
|
953
|
+
@keyframes fz-fab-menu-out {
|
|
954
|
+
from { opacity: 1; transform: translateY(0) scale(1); }
|
|
955
|
+
to { opacity: 0; transform: translateY(8px) scale(0.96); }
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/* Items arrive in the order they are read, just behind the panel. */
|
|
959
|
+
.fz-fab-menu[data-state='open'] .fz-fab-item {
|
|
960
|
+
animation: fz-fab-item-in 200ms ease-out both;
|
|
961
|
+
animation-delay: calc(60ms + var(--i, 0) * 40ms);
|
|
962
|
+
}
|
|
963
|
+
@keyframes fz-fab-item-in {
|
|
964
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
965
|
+
to { opacity: 1; transform: translateY(0); }
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/* The "+" becomes an "×" while the menu is open — the button says what tapping
|
|
969
|
+
it again will do. */
|
|
970
|
+
.fz-fab-trigger svg { transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1); }
|
|
971
|
+
.fz-fab-trigger[data-state='open'] svg { transform: rotate(135deg); }
|
|
972
|
+
|
|
973
|
+
@media (prefers-reduced-motion: reduce) {
|
|
974
|
+
.fz-fab-menu[data-state='open'],
|
|
975
|
+
.fz-fab-menu[data-state='closed'],
|
|
976
|
+
.fz-fab-menu[data-state='open'] .fz-fab-item { animation: none; }
|
|
977
|
+
.fz-fab-trigger svg { transition: none; }
|
|
978
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { WizardMedia, WizardStepDef, WizardValues } from './types';
|
|
3
|
+
export interface WizardLabels {
|
|
4
|
+
back: string;
|
|
5
|
+
next: string;
|
|
6
|
+
finish: string;
|
|
7
|
+
exit: string;
|
|
8
|
+
stepOf: string;
|
|
9
|
+
exitTitle: string;
|
|
10
|
+
exitDescription: string;
|
|
11
|
+
exitConfirm: string;
|
|
12
|
+
exitCancel: string;
|
|
13
|
+
/** Badge on a field a `suggest` answered rather than the user. */
|
|
14
|
+
suggested: string;
|
|
15
|
+
}
|
|
16
|
+
export interface WizardProps {
|
|
17
|
+
steps: ReadonlyArray<WizardStepDef>;
|
|
18
|
+
initialValues?: WizardValues;
|
|
19
|
+
draftKey?: string;
|
|
20
|
+
onSubmit: (values: WizardValues) => Promise<void> | void;
|
|
21
|
+
/** Omit to hide the exit affordance — a first-run flow with nowhere to go back to. */
|
|
22
|
+
onExit?: () => void;
|
|
23
|
+
/** Brand mark above the question. */
|
|
24
|
+
logo?: React.ReactNode;
|
|
25
|
+
/** Panel shown when the current step declares no media of its own. */
|
|
26
|
+
fallbackMedia?: WizardMedia;
|
|
27
|
+
labels?: Partial<WizardLabels>;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fullscreen, data-driven wizard: form column on the left, media panel on the right.
|
|
32
|
+
*
|
|
33
|
+
* Steps and fields are plain data (`WizardStepDef[]`), so a flow changes by editing
|
|
34
|
+
* a list rather than a component — which is the whole point for questionnaires that
|
|
35
|
+
* get reworded every time we learn something about a vertical.
|
|
36
|
+
*/
|
|
37
|
+
export declare function Wizard({ steps, initialValues, draftKey, onSubmit, onExit, logo, fallbackMedia, labels, className, }: WizardProps): React.JSX.Element | null;
|
|
38
|
+
//# sourceMappingURL=Wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wizard.d.ts","sourceRoot":"","sources":["../../src/wizard/Wizard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAA;CAClB;AAgBD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IACnC,aAAa,CAAC,EAAE,YAAY,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACxD,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,qCAAqC;IACrC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,sEAAsE;IACtE,aAAa,CAAC,EAAE,WAAW,CAAA;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAyBD;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,GACzF,EAAE,WAAW,4BAgMb"}
|