ember-primitives 0.50.0 → 0.51.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/declarations/color-scheme.d.ts +3 -1
- package/declarations/color-scheme.d.ts.map +1 -1
- package/declarations/components/breadcrumb.d.ts +58 -0
- package/declarations/components/breadcrumb.d.ts.map +1 -0
- package/declarations/components/drawer.d.ts +128 -0
- package/declarations/components/drawer.d.ts.map +1 -0
- package/declarations/index.d.ts +2 -0
- package/declarations/index.d.ts.map +1 -1
- package/dist/color-scheme.js +20 -4
- package/dist/color-scheme.js.map +1 -1
- package/dist/components/breadcrumb.js +45 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/drawer.js +123 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
- package/src/color-scheme.ts +24 -3
- package/src/components/breadcrumb.gts +73 -0
- package/src/components/drawer.gts +233 -0
- package/src/index.ts +2 -0
|
@@ -22,6 +22,8 @@ export declare const colorScheme: {
|
|
|
22
22
|
* the current valuel of the "color scheme"
|
|
23
23
|
*/
|
|
24
24
|
current: string | undefined;
|
|
25
|
+
readonly isDark: boolean;
|
|
26
|
+
readonly isLight: boolean;
|
|
25
27
|
};
|
|
26
28
|
/**
|
|
27
29
|
* Synchronizes state of `colorScheme` with the users preferences as well as reconciles with previously set theme in local storage.
|
|
@@ -36,8 +38,8 @@ export declare function sync(): void;
|
|
|
36
38
|
export declare const prefers: {
|
|
37
39
|
dark: () => boolean;
|
|
38
40
|
light: () => boolean;
|
|
39
|
-
custom: (name: string) => boolean;
|
|
40
41
|
none: () => boolean;
|
|
42
|
+
custom: (name: string) => boolean;
|
|
41
43
|
};
|
|
42
44
|
/**
|
|
43
45
|
* Helper methods for working with the color scheme preference in local storage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-scheme.d.ts","sourceRoot":"","sources":["../src/color-scheme.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;oBACa,MAAM;;QAOpB;;WAEG;2BACgB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI;;;QAKhD;;WAEG;2BACgB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI;;IAKlD;;OAEG;aACY,MAAM,GAAG,SAAS
|
|
1
|
+
{"version":3,"file":"color-scheme.d.ts","sourceRoot":"","sources":["../src/color-scheme.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;oBACa,MAAM;;QAOpB;;WAEG;2BACgB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI;;;QAKhD;;WAEG;2BACgB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI;;IAKlD;;OAEG;aACY,MAAM,GAAG,SAAS;;;CAsBlC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,IAAI,SAyBnB;AAcD;;;GAGG;AACH,eAAO,MAAM,OAAO;;;;mBAIH,MAAM;CACtB,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,eAAe;;;oBAGV,MAAM;;CAEvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,WAAW,UAInD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;AAC1E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;AAkBpD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,WAAW,QAItD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { TOC } from "@ember/component/template-only";
|
|
2
|
+
declare const Separator: TOC<{
|
|
3
|
+
Element: HTMLSpanElement;
|
|
4
|
+
Blocks: {
|
|
5
|
+
default: [];
|
|
6
|
+
};
|
|
7
|
+
}>;
|
|
8
|
+
export interface Signature {
|
|
9
|
+
Element: HTMLElement;
|
|
10
|
+
Args: {
|
|
11
|
+
/**
|
|
12
|
+
* The accessible label for the breadcrumb navigation.
|
|
13
|
+
* Defaults to "Breadcrumb"
|
|
14
|
+
*/
|
|
15
|
+
label?: string;
|
|
16
|
+
};
|
|
17
|
+
Blocks: {
|
|
18
|
+
default: [
|
|
19
|
+
{
|
|
20
|
+
/**
|
|
21
|
+
* A separator component to place between breadcrumb items.
|
|
22
|
+
* Typically renders as "/" or ">" with aria-hidden="true".
|
|
23
|
+
*/
|
|
24
|
+
Separator: typeof Separator;
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A breadcrumb navigation component that displays the current page's location within a navigational hierarchy.
|
|
31
|
+
*
|
|
32
|
+
* Breadcrumbs help users understand their current location and provide a way to navigate back through the hierarchy.
|
|
33
|
+
*
|
|
34
|
+
* For example:
|
|
35
|
+
*
|
|
36
|
+
* ```gjs live preview
|
|
37
|
+
* import { Breadcrumb } from 'ember-primitives';
|
|
38
|
+
*
|
|
39
|
+
* <template>
|
|
40
|
+
* <Breadcrumb as |b|>
|
|
41
|
+
* <li>
|
|
42
|
+
* <a href="/">Home</a>
|
|
43
|
+
* </li>
|
|
44
|
+
* <b.Separator>/</b.Separator>
|
|
45
|
+
* <li>
|
|
46
|
+
* <a href="/docs">Docs</a>
|
|
47
|
+
* </li>
|
|
48
|
+
* <b.Separator>/</b.Separator>
|
|
49
|
+
* <li aria-current="page">
|
|
50
|
+
* Breadcrumb
|
|
51
|
+
* </li>
|
|
52
|
+
* </Breadcrumb>
|
|
53
|
+
* </template>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare const Breadcrumb: TOC<Signature>;
|
|
57
|
+
export default Breadcrumb;
|
|
58
|
+
//# sourceMappingURL=breadcrumb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.d.ts","sourceRoot":"","sources":["../../src/components/breadcrumb.gts"],"names":[],"mappings":"AA2EA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AAE1D,QAAA,MAAM,SAAS,EAAE,GAAG,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE;QACN,OAAO,EAAE,EAAE,CAAC;KACb,CAAC;CACH,CAYC,CAAC;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE;QACJ;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE;QACN,OAAO,EAAE;YACP;gBACE;;;mBAGG;gBACH,SAAS,EAAE,OAAO,SAAS,CAAC;aAC7B;SACF,CAAC;KACH,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,UAAU,EAAE,GAAG,CAAC,SAAS,CAiBpC,CAAC;AAEH,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import Component from "@glimmer/component";
|
|
2
|
+
import type { TOC } from "@ember/component/template-only";
|
|
3
|
+
import type { ModifierLike, WithBoundArgs } from "@glint/template";
|
|
4
|
+
declare const DrawerElement: TOC<{
|
|
5
|
+
Element: HTMLDialogElement;
|
|
6
|
+
Args: {
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
open: boolean | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
register: ModifierLike<{
|
|
19
|
+
Element: HTMLDialogElement;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
Blocks: {
|
|
23
|
+
default: [];
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
26
|
+
export interface Signature {
|
|
27
|
+
Args: {
|
|
28
|
+
/**
|
|
29
|
+
* Optionally set the open state of the drawer
|
|
30
|
+
* The state will still be managed internally,
|
|
31
|
+
* so this does not need to be a maintained value, but whenever it changes,
|
|
32
|
+
* the drawer element will reflect that change accordingly.
|
|
33
|
+
*/
|
|
34
|
+
open?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* When the drawer is closed, this function will be called
|
|
37
|
+
* and the drawer's `returnValue` will be passed.
|
|
38
|
+
*
|
|
39
|
+
* This can be used to determine which button was clicked to close the drawer
|
|
40
|
+
*
|
|
41
|
+
* Note though that this value is only populated when using
|
|
42
|
+
* `<form method='dialog'>`
|
|
43
|
+
*/
|
|
44
|
+
onClose?: (returnValue: string) => void;
|
|
45
|
+
};
|
|
46
|
+
Blocks: {
|
|
47
|
+
default: [
|
|
48
|
+
{
|
|
49
|
+
/**
|
|
50
|
+
* Represents the open state of the drawer element.
|
|
51
|
+
*/
|
|
52
|
+
isOpen: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Closes the drawer element
|
|
55
|
+
* Will throw an error if `Drawer` is not rendered.
|
|
56
|
+
*/
|
|
57
|
+
close: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Opens the drawer element.
|
|
60
|
+
* Will throw an error if `Drawer` is not rendered.
|
|
61
|
+
*/
|
|
62
|
+
open: () => void;
|
|
63
|
+
/**
|
|
64
|
+
* This modifier should be applied to the button that opens the Drawer so that it can be re-focused when the drawer closes.
|
|
65
|
+
*
|
|
66
|
+
* Example:
|
|
67
|
+
*
|
|
68
|
+
* ```gjs
|
|
69
|
+
* <template>
|
|
70
|
+
* <Drawer as |d|>
|
|
71
|
+
* <button {{d.focusOnClose}} {{on "click" d.open}}>Open</button>
|
|
72
|
+
*
|
|
73
|
+
* <d.Drawer>...</d.Drawer>
|
|
74
|
+
* </Drawer>
|
|
75
|
+
* </template>
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
focusOnClose: ModifierLike<{
|
|
79
|
+
Element: HTMLElement;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* This is the `<dialog>` element (with some defaults pre-wired).
|
|
83
|
+
* This is required to be rendered.
|
|
84
|
+
*/
|
|
85
|
+
Drawer: WithBoundArgs<typeof DrawerElement, "onClose" | "register" | "open">;
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
declare class DrawerDialog extends Component<Signature> {
|
|
91
|
+
#private;
|
|
92
|
+
_isOpen: boolean;
|
|
93
|
+
get isOpen(): boolean;
|
|
94
|
+
set isOpen(val: boolean);
|
|
95
|
+
refocus: import("ember-modifier").FunctionBasedModifier<{
|
|
96
|
+
Args: {
|
|
97
|
+
Positional: unknown[];
|
|
98
|
+
Named: import("ember-modifier/-private/signature").EmptyObject;
|
|
99
|
+
};
|
|
100
|
+
Element: Element;
|
|
101
|
+
}>;
|
|
102
|
+
drawerElement: HTMLDialogElement | undefined;
|
|
103
|
+
register: import("ember-modifier").FunctionBasedModifier<{
|
|
104
|
+
Args: {
|
|
105
|
+
Positional: unknown[];
|
|
106
|
+
Named: import("ember-modifier/-private/signature").EmptyObject;
|
|
107
|
+
};
|
|
108
|
+
Element: HTMLDialogElement;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Closes the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
112
|
+
*/
|
|
113
|
+
close: () => void;
|
|
114
|
+
/**
|
|
115
|
+
* @internal
|
|
116
|
+
*
|
|
117
|
+
* handles the <dialog> element's native close behavior.
|
|
118
|
+
* listened to via addEventListener('close', ...);
|
|
119
|
+
*/
|
|
120
|
+
handleClose: () => void;
|
|
121
|
+
/**
|
|
122
|
+
* Opens the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
123
|
+
*/
|
|
124
|
+
open: () => void;
|
|
125
|
+
}
|
|
126
|
+
export declare const Drawer: typeof DrawerDialog;
|
|
127
|
+
export default DrawerDialog;
|
|
128
|
+
//# sourceMappingURL=drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/components/drawer.gts"],"names":[],"mappings":"AAyOA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAa3C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEnE,QAAA,MAAM,aAAa,EAAE,GAAG,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,IAAI,EAAE;QACJ;;WAEG;QACH,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;QAC1B;;WAEG;QACH,OAAO,EAAE,MAAM,IAAI,CAAC;QAEpB;;WAEG;QACH,QAAQ,EAAE,YAAY,CAAC;YAAE,OAAO,EAAE,iBAAiB,CAAA;SAAE,CAAC,CAAC;KACxD,CAAC;IACF,MAAM,EAAE;QAAE,OAAO,EAAE,EAAE,CAAA;KAAE,CAAC;CACzB,CAcC,CAAC;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE;QACJ;;;;;WAKG;QACH,IAAI,CAAC,EAAE,OAAO,CAAC;QACf;;;;;;;;WAQG;QACH,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;KACzC,CAAC;IACF,MAAM,EAAE;QACN,OAAO,EAAE;YACP;gBACE;;mBAEG;gBACH,MAAM,EAAE,OAAO,CAAC;gBAEhB;;;mBAGG;gBACH,KAAK,EAAE,MAAM,IAAI,CAAC;gBAElB;;;mBAGG;gBACH,IAAI,EAAE,MAAM,IAAI,CAAC;gBAEjB;;;;;;;;;;;;;;mBAcG;gBACH,YAAY,EAAE,YAAY,CAAC;oBAAE,OAAO,EAAE,WAAW,CAAA;iBAAE,CAAC,CAAC;gBAErD;;;mBAGG;gBACH,MAAM,EAAE,aAAa,CAAC,OAAO,aAAa,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC;aAC9E;SACF,CAAC;KACH,CAAC;CACH;AAED,cAAM,YAAa,SAAQ,SAAS,CAAC,SAAS,CAAC;;IAab,OAAO,EAAE,OAAO,CAAC;IAEjD,IAAI,MAAM,IAMM,OAAO,CADtB;IACD,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,EAEtB;IAGD,OAAO;;;;;;OAQJ;IAEc,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAE9D,QAAQ;;;;;;OAiBL;IAEH;;OAEG;IACH,KAAK,aAkBH;IAEF;;;;;OAKG;IACH,WAAW,aAUT;IAEF;;OAEG;IACH,IAAI,aAkBF;CACH;AAED,eAAO,MAAM,MAAM,qBAAe,CAAC;AAEnC,eAAe,YAAY,CAAC"}
|
package/declarations/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { Accordion } from './components/accordion';
|
|
2
2
|
export type { AccordionContentExternalSignature, AccordionHeaderExternalSignature, AccordionItemExternalSignature, AccordionTriggerExternalSignature, } from './components/accordion/public.ts';
|
|
3
3
|
export { Avatar } from './components/avatar';
|
|
4
|
+
export { Breadcrumb } from './components/breadcrumb';
|
|
4
5
|
export { Dialog, Dialog as Modal } from './components/dialog';
|
|
6
|
+
export { Drawer } from './components/drawer';
|
|
5
7
|
export { ExternalLink } from './components/external-link';
|
|
6
8
|
export { Form } from './components/form';
|
|
7
9
|
export { Key, KeyCombo } from './components/keys';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,iCAAiC,EACjC,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,iCAAiC,EACjC,gCAAgC,EAChC,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,cAAc,cAAc,CAAC"}
|
package/dist/color-scheme.js
CHANGED
|
@@ -51,6 +51,12 @@ const colorScheme = {
|
|
|
51
51
|
}
|
|
52
52
|
localPreference.update(value);
|
|
53
53
|
setColorScheme(value);
|
|
54
|
+
},
|
|
55
|
+
get isDark() {
|
|
56
|
+
return _colorScheme.current === 'dark';
|
|
57
|
+
},
|
|
58
|
+
get isLight() {
|
|
59
|
+
return _colorScheme.current !== 'dark';
|
|
54
60
|
}
|
|
55
61
|
};
|
|
56
62
|
|
|
@@ -82,16 +88,25 @@ function sync() {
|
|
|
82
88
|
_colorScheme.current = 'light';
|
|
83
89
|
}
|
|
84
90
|
}
|
|
91
|
+
const queries = {
|
|
92
|
+
dark: window.matchMedia('(prefers-color-scheme: dark)'),
|
|
93
|
+
light: window.matchMedia('(prefers-color-scheme: light)'),
|
|
94
|
+
none: window.matchMedia('(prefers-color-scheme: no-preference)')
|
|
95
|
+
};
|
|
96
|
+
queries.dark.addEventListener('change', e => {
|
|
97
|
+
const mode = e.matches ? 'dark' : 'light';
|
|
98
|
+
colorScheme.update(mode);
|
|
99
|
+
});
|
|
85
100
|
|
|
86
101
|
/**
|
|
87
102
|
* Helper methods to determining what the user's preferred color scheme is
|
|
88
103
|
* based on the system preferences rather than the users explicit preference.
|
|
89
104
|
*/
|
|
90
105
|
const prefers = {
|
|
91
|
-
dark: () =>
|
|
92
|
-
light: () =>
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
dark: () => queries.dark.matches,
|
|
107
|
+
light: () => queries.light.matches,
|
|
108
|
+
none: () => queries.none.matches,
|
|
109
|
+
custom: name => window.matchMedia(`(prefers-color-scheme: ${name})`).matches
|
|
95
110
|
};
|
|
96
111
|
const LOCAL_PREF_KEY = 'ember-primitives/color-scheme#local-preference';
|
|
97
112
|
|
|
@@ -137,6 +152,7 @@ function styleOf(element) {
|
|
|
137
152
|
}
|
|
138
153
|
return document.documentElement.style;
|
|
139
154
|
}
|
|
155
|
+
sync();
|
|
140
156
|
|
|
141
157
|
export { colorScheme, getColorScheme, localPreference, prefers, removeColorScheme, setColorScheme, sync };
|
|
142
158
|
//# sourceMappingURL=color-scheme.js.map
|
package/dist/color-scheme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-scheme.js","sources":["../src/color-scheme.ts"],"sourcesContent":["import { waitForPromise } from '@ember/test-waiters';\n\nimport { cell } from 'ember-resources';\n\nconst _colorScheme = cell<string | undefined>();\n\nlet callbacks: Set<(colorScheme: string) => void> = new Set();\n\nasync function runCallbacks(theme: string) {\n await Promise.resolve();\n\n for (const callback of callbacks.values()) {\n callback(theme);\n }\n}\n\n/**\n * Object for managing the color scheme\n */\nexport const colorScheme = {\n /**\n * Set's the current color scheme to the passed value\n */\n update: (value: string) => {\n colorScheme.current = value;\n\n void waitForPromise(runCallbacks(value));\n },\n\n on: {\n /**\n * register a function to be called when the color scheme changes.\n */\n update: (callback: (colorScheme: string) => void) => {\n callbacks.add(callback);\n },\n },\n off: {\n /**\n * unregister a function that would have been called when the color scheme changes.\n */\n update: (callback: (colorScheme: string) => void) => {\n callbacks.delete(callback);\n },\n },\n\n /**\n * the current valuel of the \"color scheme\"\n */\n get current(): string | undefined {\n return _colorScheme.current;\n },\n set current(value: string | undefined) {\n _colorScheme.current = value;\n\n if (!value) {\n localPreference.delete();\n\n return;\n }\n\n localPreference.update(value);\n setColorScheme(value);\n },\n};\n\n/**\n * Synchronizes state of `colorScheme` with the users preferences as well as reconciles with previously set theme in local storage.\n *\n * This may only be called once per app.\n */\nexport function sync() {\n /**\n * reset the callbacks\n */\n callbacks = new Set();\n\n /**\n * If local prefs are set, then we don't care what prefers-color-scheme is\n */\n const userPreference = localPreference.read();\n\n if (userPreference) {\n setColorScheme(userPreference);\n _colorScheme.current = userPreference;\n\n return;\n }\n\n if (prefers.dark()) {\n setColorScheme('dark');\n _colorScheme.current = 'dark';\n } else if (prefers.light()) {\n setColorScheme('light');\n _colorScheme.current = 'light';\n }\n}\n\n/**\n * Helper methods to determining what the user's preferred color scheme is\n * based on the system preferences rather than the users explicit preference.\n */\nexport const prefers = {\n dark: () =>
|
|
1
|
+
{"version":3,"file":"color-scheme.js","sources":["../src/color-scheme.ts"],"sourcesContent":["import { waitForPromise } from '@ember/test-waiters';\n\nimport { cell } from 'ember-resources';\n\nconst _colorScheme = cell<string | undefined>();\n\nlet callbacks: Set<(colorScheme: string) => void> = new Set();\n\nasync function runCallbacks(theme: string) {\n await Promise.resolve();\n\n for (const callback of callbacks.values()) {\n callback(theme);\n }\n}\n\n/**\n * Object for managing the color scheme\n */\nexport const colorScheme = {\n /**\n * Set's the current color scheme to the passed value\n */\n update: (value: string) => {\n colorScheme.current = value;\n\n void waitForPromise(runCallbacks(value));\n },\n\n on: {\n /**\n * register a function to be called when the color scheme changes.\n */\n update: (callback: (colorScheme: string) => void) => {\n callbacks.add(callback);\n },\n },\n off: {\n /**\n * unregister a function that would have been called when the color scheme changes.\n */\n update: (callback: (colorScheme: string) => void) => {\n callbacks.delete(callback);\n },\n },\n\n /**\n * the current valuel of the \"color scheme\"\n */\n get current(): string | undefined {\n return _colorScheme.current;\n },\n set current(value: string | undefined) {\n _colorScheme.current = value;\n\n if (!value) {\n localPreference.delete();\n\n return;\n }\n\n localPreference.update(value);\n setColorScheme(value);\n },\n\n get isDark() {\n return _colorScheme.current === 'dark';\n },\n get isLight() {\n return _colorScheme.current !== 'dark';\n },\n};\n\n/**\n * Synchronizes state of `colorScheme` with the users preferences as well as reconciles with previously set theme in local storage.\n *\n * This may only be called once per app.\n */\nexport function sync() {\n /**\n * reset the callbacks\n */\n callbacks = new Set();\n\n /**\n * If local prefs are set, then we don't care what prefers-color-scheme is\n */\n const userPreference = localPreference.read();\n\n if (userPreference) {\n setColorScheme(userPreference);\n _colorScheme.current = userPreference;\n\n return;\n }\n\n if (prefers.dark()) {\n setColorScheme('dark');\n _colorScheme.current = 'dark';\n } else if (prefers.light()) {\n setColorScheme('light');\n _colorScheme.current = 'light';\n }\n}\n\nconst queries = {\n dark: window.matchMedia('(prefers-color-scheme: dark)'),\n light: window.matchMedia('(prefers-color-scheme: light)'),\n none: window.matchMedia('(prefers-color-scheme: no-preference)'),\n};\n\nqueries.dark.addEventListener('change', (e) => {\n const mode = e.matches ? 'dark' : 'light';\n\n colorScheme.update(mode);\n});\n\n/**\n * Helper methods to determining what the user's preferred color scheme is\n * based on the system preferences rather than the users explicit preference.\n */\nexport const prefers = {\n dark: () => queries.dark.matches,\n light: () => queries.light.matches,\n none: () => queries.none.matches,\n custom: (name: string) => window.matchMedia(`(prefers-color-scheme: ${name})`).matches,\n};\n\nconst LOCAL_PREF_KEY = 'ember-primitives/color-scheme#local-preference';\n\n/**\n * Helper methods for working with the color scheme preference in local storage\n */\nexport const localPreference = {\n isSet: () => Boolean(localPreference.read()),\n read: () => localStorage.getItem(LOCAL_PREF_KEY),\n update: (value: string) => localStorage.setItem(LOCAL_PREF_KEY, value),\n delete: () => localStorage.removeItem(LOCAL_PREF_KEY),\n};\n\n/**\n * For the given element, returns the `color-scheme` of that element.\n */\nexport function getColorScheme(element?: HTMLElement) {\n const style = styleOf(element);\n\n return style.getPropertyValue('color-scheme');\n}\n\nexport function setColorScheme(element: HTMLElement, value: string): void;\nexport function setColorScheme(value: string): void;\n\nexport function setColorScheme(...args: [string] | [HTMLElement, string]): void {\n if (typeof args[0] === 'string') {\n styleOf().setProperty('color-scheme', args[0]);\n\n return;\n }\n\n if (typeof args[1] === 'string') {\n styleOf(args[0]).setProperty('color-scheme', args[1]);\n\n return;\n }\n\n throw new Error(`Invalid arity, expected up to 2 args, received ${args.length}`);\n}\n\n/**\n * Removes the `color-scheme` from the given element\n */\nexport function removeColorScheme(element?: HTMLElement) {\n const style = styleOf(element);\n\n style.removeProperty('color-scheme');\n}\n\nfunction styleOf(element?: HTMLElement) {\n if (element) {\n return element.style;\n }\n\n return document.documentElement.style;\n}\n\nsync();\n"],"names":["_colorScheme","cell","callbacks","Set","runCallbacks","theme","Promise","resolve","callback","values","colorScheme","update","value","current","waitForPromise","on","add","off","delete","localPreference","setColorScheme","isDark","isLight","sync","userPreference","read","prefers","dark","light","queries","window","matchMedia","none","addEventListener","e","mode","matches","custom","name","LOCAL_PREF_KEY","isSet","Boolean","localStorage","getItem","setItem","removeItem","getColorScheme","element","style","styleOf","getPropertyValue","args","setProperty","Error","length","removeColorScheme","removeProperty","document","documentElement"],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { hash } from '@ember/helper';
|
|
2
|
+
import { precompileTemplate } from '@ember/template-compilation';
|
|
3
|
+
import { setComponentTemplate } from '@ember/component';
|
|
4
|
+
import templateOnly from '@ember/component/template-only';
|
|
5
|
+
|
|
6
|
+
const Separator = setComponentTemplate(precompileTemplate("<span aria-hidden=\"true\" ...attributes>\n {{yield}}\n</span>", {
|
|
7
|
+
strictMode: true
|
|
8
|
+
}), templateOnly());
|
|
9
|
+
/**
|
|
10
|
+
* A breadcrumb navigation component that displays the current page's location within a navigational hierarchy.
|
|
11
|
+
*
|
|
12
|
+
* Breadcrumbs help users understand their current location and provide a way to navigate back through the hierarchy.
|
|
13
|
+
*
|
|
14
|
+
* For example:
|
|
15
|
+
*
|
|
16
|
+
* ```gjs live preview
|
|
17
|
+
* import { Breadcrumb } from 'ember-primitives';
|
|
18
|
+
*
|
|
19
|
+
* <template>
|
|
20
|
+
* <Breadcrumb as |b|>
|
|
21
|
+
* <li>
|
|
22
|
+
* <a href="/">Home</a>
|
|
23
|
+
* </li>
|
|
24
|
+
* <b.Separator>/</b.Separator>
|
|
25
|
+
* <li>
|
|
26
|
+
* <a href="/docs">Docs</a>
|
|
27
|
+
* </li>
|
|
28
|
+
* <b.Separator>/</b.Separator>
|
|
29
|
+
* <li aria-current="page">
|
|
30
|
+
* Breadcrumb
|
|
31
|
+
* </li>
|
|
32
|
+
* </Breadcrumb>
|
|
33
|
+
* </template>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
const Breadcrumb = setComponentTemplate(precompileTemplate("<nav aria-label={{if @label @label \"Breadcrumb\"}} ...attributes>\n <ol>\n {{yield (hash Separator=Separator)}}\n </ol>\n</nav>", {
|
|
37
|
+
strictMode: true,
|
|
38
|
+
scope: () => ({
|
|
39
|
+
hash,
|
|
40
|
+
Separator
|
|
41
|
+
})
|
|
42
|
+
}), templateOnly());
|
|
43
|
+
|
|
44
|
+
export { Breadcrumb, Breadcrumb as default };
|
|
45
|
+
//# sourceMappingURL=breadcrumb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.js","sources":["../../src/components/breadcrumb.gts"],"sourcesContent":["import { hash } from \"@ember/helper\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nconst Separator: TOC<{\n Element: HTMLSpanElement;\n Blocks: {\n default: [];\n };\n}> = <template>\n <span aria-hidden=\"true\" ...attributes>\n {{yield}}\n </span>\n</template>;\n\nexport interface Signature {\n Element: HTMLElement;\n Args: {\n /**\n * The accessible label for the breadcrumb navigation.\n * Defaults to \"Breadcrumb\"\n */\n label?: string;\n };\n Blocks: {\n default: [\n {\n /**\n * A separator component to place between breadcrumb items.\n * Typically renders as \"/\" or \">\" with aria-hidden=\"true\".\n */\n Separator: typeof Separator;\n },\n ];\n };\n}\n\n/**\n * A breadcrumb navigation component that displays the current page's location within a navigational hierarchy.\n *\n * Breadcrumbs help users understand their current location and provide a way to navigate back through the hierarchy.\n *\n * For example:\n *\n * ```gjs live preview\n * import { Breadcrumb } from 'ember-primitives';\n *\n * <template>\n * <Breadcrumb as |b|>\n * <li>\n * <a href=\"/\">Home</a>\n * </li>\n * <b.Separator>/</b.Separator>\n * <li>\n * <a href=\"/docs\">Docs</a>\n * </li>\n * <b.Separator>/</b.Separator>\n * <li aria-current=\"page\">\n * Breadcrumb\n * </li>\n * </Breadcrumb>\n * </template>\n * ```\n */\nexport const Breadcrumb: TOC<Signature> = <template>\n <nav aria-label={{if @label @label \"Breadcrumb\"}} ...attributes>\n <ol>\n {{yield (hash Separator=Separator)}}\n </ol>\n </nav>\n</template>;\n\nexport default Breadcrumb;\n"],"names":["Separator","setComponentTemplate","precompileTemplate","strictMode","templateOnly","Breadcrumb","scope","hash"],"mappings":";;;;;AAIA,MAAMA,SAKD,GAAAC,oBAAA,CAAAC,kBAAA,CAAA,iEAAA,EAIL;EAAAC,UAAA,EAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA,CAAA;AAwBV;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BC;MACYC,UAAgB,GAAAJ,oBAAA,CAAaC,kBAAA,CAAA,uIAAA,EAM1C;EAAAC,UAAA,EAAA,IAAA;AAAAG,EAAAA,KAAA,EAAAA,OAAA;IAAAC,IAAA;AAAAP,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAI,YAAA,EAAA;;;;"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { assert } from '@ember/debug';
|
|
4
|
+
import { hash } from '@ember/helper';
|
|
5
|
+
import { on } from '@ember/modifier';
|
|
6
|
+
import { modifier } from 'ember-modifier';
|
|
7
|
+
import { localCopy } from 'tracked-toolbox';
|
|
8
|
+
import { precompileTemplate } from '@ember/template-compilation';
|
|
9
|
+
import { setComponentTemplate } from '@ember/component';
|
|
10
|
+
import templateOnly from '@ember/component/template-only';
|
|
11
|
+
import { g, i } from 'decorator-transforms/runtime';
|
|
12
|
+
|
|
13
|
+
const DrawerElement = setComponentTemplate(precompileTemplate("<dialog ...attributes open={{@open}} {{on \"close\" @onClose}} {{@register}}>\n {{yield}}\n</dialog>", {
|
|
14
|
+
strictMode: true,
|
|
15
|
+
scope: () => ({
|
|
16
|
+
on
|
|
17
|
+
})
|
|
18
|
+
}), templateOnly());
|
|
19
|
+
class DrawerDialog extends Component {
|
|
20
|
+
static {
|
|
21
|
+
setComponentTemplate(precompileTemplate("{{yield (hash isOpen=this.isOpen open=this.open close=this.close focusOnClose=this.refocus Drawer=(component DrawerElement open=@open onClose=this.handleClose register=this.register))}}", {
|
|
22
|
+
strictMode: true,
|
|
23
|
+
scope: () => ({
|
|
24
|
+
hash,
|
|
25
|
+
DrawerElement
|
|
26
|
+
})
|
|
27
|
+
}), this);
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
30
|
+
static {
|
|
31
|
+
g(this.prototype, "_isOpen", [localCopy("args.open")]);
|
|
32
|
+
}
|
|
33
|
+
#_isOpen = (i(this, "_isOpen"), void 0);
|
|
34
|
+
get isOpen() {
|
|
35
|
+
/**
|
|
36
|
+
* Always fallback to false (closed)
|
|
37
|
+
*/
|
|
38
|
+
return this._isOpen ?? false;
|
|
39
|
+
}
|
|
40
|
+
set isOpen(val) {
|
|
41
|
+
this._isOpen = val;
|
|
42
|
+
}
|
|
43
|
+
#lastIsOpen = false;
|
|
44
|
+
refocus = modifier(element => {
|
|
45
|
+
assert(`focusOnClose is only valid on a HTMLElement`, element instanceof HTMLElement);
|
|
46
|
+
if (!this.isOpen && this.#lastIsOpen) {
|
|
47
|
+
element.focus();
|
|
48
|
+
}
|
|
49
|
+
this.#lastIsOpen = this.isOpen;
|
|
50
|
+
});
|
|
51
|
+
static {
|
|
52
|
+
g(this.prototype, "drawerElement", [tracked]);
|
|
53
|
+
}
|
|
54
|
+
#drawerElement = (i(this, "drawerElement"), void 0);
|
|
55
|
+
register = modifier(element => {
|
|
56
|
+
/**
|
|
57
|
+
* This is very sad.
|
|
58
|
+
*
|
|
59
|
+
* But we need the element to be 'root state'
|
|
60
|
+
* so that when we read things like "isOpen",
|
|
61
|
+
* when the drawer is finally rendered, all the
|
|
62
|
+
* downstream properties render.
|
|
63
|
+
*
|
|
64
|
+
* This has to be an async / delayed a bit, so that
|
|
65
|
+
* the tracking frame can exit, and we don't infinite loop
|
|
66
|
+
*/
|
|
67
|
+
void (async () => {
|
|
68
|
+
await Promise.resolve();
|
|
69
|
+
this.drawerElement = element;
|
|
70
|
+
})();
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Closes the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
74
|
+
*/
|
|
75
|
+
close = () => {
|
|
76
|
+
assert("Cannot call `close` on <Drawer> without rendering the drawer element.", this.drawerElement);
|
|
77
|
+
/**
|
|
78
|
+
* If the element is already closed, don't run all this again
|
|
79
|
+
*/
|
|
80
|
+
if (!this.drawerElement.hasAttribute("open")) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* removes the `open` attribute
|
|
85
|
+
* handleClose will be called because the drawer has bound the `close` event.
|
|
86
|
+
*/
|
|
87
|
+
this.drawerElement.close();
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* @internal
|
|
91
|
+
*
|
|
92
|
+
* handles the <dialog> element's native close behavior.
|
|
93
|
+
* listened to via addEventListener('close', ...);
|
|
94
|
+
*/
|
|
95
|
+
handleClose = () => {
|
|
96
|
+
assert("Cannot call `handleClose` on <Drawer> without rendering the drawer element. This is likely a bug in ember-primitives. Please open an issue <3", this.drawerElement);
|
|
97
|
+
this.isOpen = false;
|
|
98
|
+
this.args.onClose?.(this.drawerElement.returnValue);
|
|
99
|
+
// the return value ends up staying... which is annoying
|
|
100
|
+
this.drawerElement.returnValue = "";
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Opens the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
104
|
+
*/
|
|
105
|
+
open = () => {
|
|
106
|
+
assert("Cannot call `open` on <Drawer> without rendering the drawer element.", this.drawerElement);
|
|
107
|
+
/**
|
|
108
|
+
* If the element is already open, don't run all this again
|
|
109
|
+
*/
|
|
110
|
+
if (this.drawerElement.hasAttribute("open")) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* adds the `open` attribute
|
|
115
|
+
*/
|
|
116
|
+
this.drawerElement.showModal();
|
|
117
|
+
this.isOpen = true;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const Drawer = DrawerDialog;
|
|
121
|
+
|
|
122
|
+
export { Drawer, DrawerDialog as default };
|
|
123
|
+
//# sourceMappingURL=drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawer.js","sources":["../../src/components/drawer.gts"],"sourcesContent":["import Component from \"@glimmer/component\";\nimport { tracked } from \"@glimmer/tracking\";\nimport { assert } from \"@ember/debug\";\nimport { hash } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\n\nimport { modifier as eModifier } from \"ember-modifier\";\n// temp\n// https://github.com/tracked-tools/tracked-toolbox/issues/38\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error\nimport { localCopy } from \"tracked-toolbox\";\n\nimport type { TOC } from \"@ember/component/template-only\";\nimport type { ModifierLike, WithBoundArgs } from \"@glint/template\";\n\nconst DrawerElement: TOC<{\n Element: HTMLDialogElement;\n Args: {\n /**\n * @internal\n */\n open: boolean | undefined;\n /**\n * @internal\n */\n onClose: () => void;\n\n /**\n * @internal\n */\n register: ModifierLike<{ Element: HTMLDialogElement }>;\n };\n Blocks: { default: [] };\n}> = <template>\n <dialog ...attributes open={{@open}} {{on \"close\" @onClose}} {{@register}}>\n {{yield}}\n </dialog>\n</template>;\n\nexport interface Signature {\n Args: {\n /**\n * Optionally set the open state of the drawer\n * The state will still be managed internally,\n * so this does not need to be a maintained value, but whenever it changes,\n * the drawer element will reflect that change accordingly.\n */\n open?: boolean;\n /**\n * When the drawer is closed, this function will be called\n * and the drawer's `returnValue` will be passed.\n *\n * This can be used to determine which button was clicked to close the drawer\n *\n * Note though that this value is only populated when using\n * `<form method='dialog'>`\n */\n onClose?: (returnValue: string) => void;\n };\n Blocks: {\n default: [\n {\n /**\n * Represents the open state of the drawer element.\n */\n isOpen: boolean;\n\n /**\n * Closes the drawer element\n * Will throw an error if `Drawer` is not rendered.\n */\n close: () => void;\n\n /**\n * Opens the drawer element.\n * Will throw an error if `Drawer` is not rendered.\n */\n open: () => void;\n\n /**\n * This modifier should be applied to the button that opens the Drawer so that it can be re-focused when the drawer closes.\n *\n * Example:\n *\n * ```gjs\n * <template>\n * <Drawer as |d|>\n * <button {{d.focusOnClose}} {{on \"click\" d.open}}>Open</button>\n *\n * <d.Drawer>...</d.Drawer>\n * </Drawer>\n * </template>\n * ```\n */\n focusOnClose: ModifierLike<{ Element: HTMLElement }>;\n\n /**\n * This is the `<dialog>` element (with some defaults pre-wired).\n * This is required to be rendered.\n */\n Drawer: WithBoundArgs<typeof DrawerElement, \"onClose\" | \"register\" | \"open\">;\n },\n ];\n };\n}\n\nclass DrawerDialog extends Component<Signature> {\n <template>\n {{yield\n (hash\n isOpen=this.isOpen\n open=this.open\n close=this.close\n focusOnClose=this.refocus\n Drawer=(component DrawerElement open=@open onClose=this.handleClose register=this.register)\n )\n }}\n </template>\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n @localCopy(\"args.open\") declare _isOpen: boolean;\n\n get isOpen() {\n /**\n * Always fallback to false (closed)\n */\n return this._isOpen ?? false;\n }\n set isOpen(val: boolean) {\n this._isOpen = val;\n }\n\n #lastIsOpen = false;\n refocus = eModifier((element) => {\n assert(`focusOnClose is only valid on a HTMLElement`, element instanceof HTMLElement);\n\n if (!this.isOpen && this.#lastIsOpen) {\n element.focus();\n }\n\n this.#lastIsOpen = this.isOpen;\n });\n\n @tracked declare drawerElement: HTMLDialogElement | undefined;\n\n register = eModifier((element: HTMLDialogElement) => {\n /**\n * This is very sad.\n *\n * But we need the element to be 'root state'\n * so that when we read things like \"isOpen\",\n * when the drawer is finally rendered, all the\n * downstream properties render.\n *\n * This has to be an async / delayed a bit, so that\n * the tracking frame can exit, and we don't infinite loop\n */\n void (async () => {\n await Promise.resolve();\n\n this.drawerElement = element;\n })();\n });\n\n /**\n * Closes the drawer -- this will throw an error in development if the drawer element was not rendered\n */\n close = () => {\n assert(\n \"Cannot call `close` on <Drawer> without rendering the drawer element.\",\n this.drawerElement,\n );\n\n /**\n * If the element is already closed, don't run all this again\n */\n if (!this.drawerElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * removes the `open` attribute\n * handleClose will be called because the drawer has bound the `close` event.\n */\n this.drawerElement.close();\n };\n\n /**\n * @internal\n *\n * handles the <dialog> element's native close behavior.\n * listened to via addEventListener('close', ...);\n */\n handleClose = () => {\n assert(\n \"Cannot call `handleClose` on <Drawer> without rendering the drawer element. This is likely a bug in ember-primitives. Please open an issue <3\",\n this.drawerElement,\n );\n\n this.isOpen = false;\n this.args.onClose?.(this.drawerElement.returnValue);\n // the return value ends up staying... which is annoying\n this.drawerElement.returnValue = \"\";\n };\n\n /**\n * Opens the drawer -- this will throw an error in development if the drawer element was not rendered\n */\n open = () => {\n assert(\n \"Cannot call `open` on <Drawer> without rendering the drawer element.\",\n this.drawerElement,\n );\n\n /**\n * If the element is already open, don't run all this again\n */\n if (this.drawerElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * adds the `open` attribute\n */\n this.drawerElement.showModal();\n this.isOpen = true;\n };\n}\n\nexport const Drawer = DrawerDialog;\n\nexport default DrawerDialog;\n"],"names":["DrawerElement","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly","DrawerDialog","Component","hash","g","prototype","localCopy","i","isOpen","_isOpen","val","refocus","eModifier","element","assert","HTMLElement","focus","tracked","register","Promise","resolve","drawerElement","close","hasAttribute","handleClose","args","onClose","returnValue","open","showModal","Drawer"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { macroCondition, isDevelopingApp, importSync } from '@embroider/macros';
|
|
2
2
|
export { Accordion } from './components/accordion.js';
|
|
3
3
|
export { Avatar } from './components/avatar.js';
|
|
4
|
+
export { Breadcrumb } from './components/breadcrumb.js';
|
|
4
5
|
export { Dialog, Dialog as Modal } from './components/dialog.js';
|
|
6
|
+
export { Drawer } from './components/drawer.js';
|
|
5
7
|
export { ExternalLink } from './components/external-link.js';
|
|
6
8
|
export { Form } from './components/form.js';
|
|
7
9
|
export { Key, KeyCombo } from './components/keys.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * DANGER: this is a *barrel file*\n *\n * It forces the whole library to be loaded and all dependencies.\n *\n * If you have a small app, you probably don't want to import from here -- instead import from each sub-path.\n */\nimport { importSync, isDevelopingApp, macroCondition } from '@embroider/macros';\n\nif (macroCondition(isDevelopingApp())) {\n importSync('./components/violations.css');\n}\n\nexport { Accordion } from './components/accordion.gts';\nexport type {\n AccordionContentExternalSignature,\n AccordionHeaderExternalSignature,\n AccordionItemExternalSignature,\n AccordionTriggerExternalSignature,\n} from './components/accordion/public.ts';\nexport { Avatar } from './components/avatar.gts';\nexport { Dialog, Dialog as Modal } from './components/dialog.gts';\nexport { ExternalLink } from './components/external-link.gts';\nexport { Form } from './components/form.gts';\nexport { Key, KeyCombo } from './components/keys.gts';\nexport { StickyFooter } from './components/layout/sticky-footer.gts';\nexport { Link } from './components/link.gts';\nexport { Menu } from './components/menu.gts';\nexport { OTP, OTPInput } from './components/one-time-password.gts';\nexport { Popover } from './components/popover.gts';\nexport { Portal } from './components/portal.gts';\nexport { PortalTargets } from './components/portal-targets.gts';\nexport { TARGETS as PORTALS } from './components/portal-targets.gts';\nexport { Progress } from './components/progress.gts';\nexport { Rating } from './components/rating.gts';\nexport { Scroller } from './components/scroller.gts';\nexport { Shadowed } from './components/shadowed.gts';\nexport { Switch } from './components/switch.gts';\nexport { Toggle } from './components/toggle.gts';\nexport { ToggleGroup } from './components/toggle-group.gts';\nexport { VisuallyHidden } from './components/visually-hidden.gts';\nexport { Zoetrope } from './components/zoetrope.ts';\nexport * from './helpers.ts';\n"],"names":["macroCondition","isDevelopingApp","importSync"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * DANGER: this is a *barrel file*\n *\n * It forces the whole library to be loaded and all dependencies.\n *\n * If you have a small app, you probably don't want to import from here -- instead import from each sub-path.\n */\nimport { importSync, isDevelopingApp, macroCondition } from '@embroider/macros';\n\nif (macroCondition(isDevelopingApp())) {\n importSync('./components/violations.css');\n}\n\nexport { Accordion } from './components/accordion.gts';\nexport type {\n AccordionContentExternalSignature,\n AccordionHeaderExternalSignature,\n AccordionItemExternalSignature,\n AccordionTriggerExternalSignature,\n} from './components/accordion/public.ts';\nexport { Avatar } from './components/avatar.gts';\nexport { Breadcrumb } from './components/breadcrumb.gts';\nexport { Dialog, Dialog as Modal } from './components/dialog.gts';\nexport { Drawer } from './components/drawer.gts';\nexport { ExternalLink } from './components/external-link.gts';\nexport { Form } from './components/form.gts';\nexport { Key, KeyCombo } from './components/keys.gts';\nexport { StickyFooter } from './components/layout/sticky-footer.gts';\nexport { Link } from './components/link.gts';\nexport { Menu } from './components/menu.gts';\nexport { OTP, OTPInput } from './components/one-time-password.gts';\nexport { Popover } from './components/popover.gts';\nexport { Portal } from './components/portal.gts';\nexport { PortalTargets } from './components/portal-targets.gts';\nexport { TARGETS as PORTALS } from './components/portal-targets.gts';\nexport { Progress } from './components/progress.gts';\nexport { Rating } from './components/rating.gts';\nexport { Scroller } from './components/scroller.gts';\nexport { Shadowed } from './components/shadowed.gts';\nexport { Switch } from './components/switch.gts';\nexport { Toggle } from './components/toggle.gts';\nexport { ToggleGroup } from './components/toggle-group.gts';\nexport { VisuallyHidden } from './components/visually-hidden.gts';\nexport { Zoetrope } from './components/zoetrope.ts';\nexport * from './helpers.ts';\n"],"names":["macroCondition","isDevelopingApp","importSync"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,IAAIA,cAAc,CAACC,eAAe,EAAE,CAAC,EAAE;EACrCC,UAAU,CAAC,6BAA6B,CAAC;AAC3C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-primitives",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Making apps easier to build",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -17,19 +17,19 @@
|
|
|
17
17
|
],
|
|
18
18
|
"bin": "./bin/index.mjs",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@babel/runtime": "^7.
|
|
21
|
-
"@embroider/addon-shim": "^1.10.
|
|
20
|
+
"@babel/runtime": "^7.28.4",
|
|
21
|
+
"@embroider/addon-shim": "^1.10.2",
|
|
22
22
|
"@embroider/macros": "^1.19.6",
|
|
23
23
|
"@floating-ui/dom": "^1.7.0",
|
|
24
24
|
"decorator-transforms": "^2.3.0",
|
|
25
|
-
"ember-element-helper": "
|
|
25
|
+
"ember-element-helper": "^0.8.8",
|
|
26
26
|
"form-data-utils": "^0.6.0",
|
|
27
|
-
"reactiveweb": "^1.
|
|
27
|
+
"reactiveweb": "^1.9.1",
|
|
28
28
|
"should-handle-link": "^1.2.2",
|
|
29
29
|
"tabster": "^8.7.0",
|
|
30
30
|
"tracked-built-ins": "^4.1.0",
|
|
31
31
|
"tracked-toolbox": "^2.0.0",
|
|
32
|
-
"which-heading-do-i-need": "0.2.
|
|
32
|
+
"which-heading-do-i-need": "0.2.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@arethetypeswrong/cli": "^0.18.0",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"concurrently": "^9.2.1",
|
|
59
59
|
"ember-modifier": "^4.2.2",
|
|
60
60
|
"ember-resources": "^7.0.7",
|
|
61
|
-
"ember-source": "6.9.0",
|
|
61
|
+
"ember-source": "^6.9.0",
|
|
62
62
|
"ember-template-lint": "^7.9.3",
|
|
63
63
|
"eslint": "^9.39.2",
|
|
64
64
|
"execa": "^9.6.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"prettier": "^3.7.4",
|
|
67
67
|
"prettier-plugin-ember-template-tag": "^2.1.2",
|
|
68
68
|
"publint": "^0.3.16",
|
|
69
|
-
"rollup": "
|
|
69
|
+
"rollup": "^4.54.0",
|
|
70
70
|
"rollup-plugin-copy": "^3.5.0",
|
|
71
71
|
"typescript": "^5.9.3"
|
|
72
72
|
},
|
|
@@ -144,6 +144,7 @@
|
|
|
144
144
|
"lint:types": "ember-tsc --noEmit --declaration false --declarationMap false --emitDeclarationOnly false",
|
|
145
145
|
"pack": "pnpm pack",
|
|
146
146
|
"start": "rollup --config --watch",
|
|
147
|
+
"dev": "rollup --config --watch --no-watch.clearScreen",
|
|
147
148
|
"test": "echo 'A v2 addon does not have tests, run tests in test-app'"
|
|
148
149
|
}
|
|
149
150
|
}
|
package/src/color-scheme.ts
CHANGED
|
@@ -62,6 +62,13 @@ export const colorScheme = {
|
|
|
62
62
|
localPreference.update(value);
|
|
63
63
|
setColorScheme(value);
|
|
64
64
|
},
|
|
65
|
+
|
|
66
|
+
get isDark() {
|
|
67
|
+
return _colorScheme.current === 'dark';
|
|
68
|
+
},
|
|
69
|
+
get isLight() {
|
|
70
|
+
return _colorScheme.current !== 'dark';
|
|
71
|
+
},
|
|
65
72
|
};
|
|
66
73
|
|
|
67
74
|
/**
|
|
@@ -96,15 +103,27 @@ export function sync() {
|
|
|
96
103
|
}
|
|
97
104
|
}
|
|
98
105
|
|
|
106
|
+
const queries = {
|
|
107
|
+
dark: window.matchMedia('(prefers-color-scheme: dark)'),
|
|
108
|
+
light: window.matchMedia('(prefers-color-scheme: light)'),
|
|
109
|
+
none: window.matchMedia('(prefers-color-scheme: no-preference)'),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
queries.dark.addEventListener('change', (e) => {
|
|
113
|
+
const mode = e.matches ? 'dark' : 'light';
|
|
114
|
+
|
|
115
|
+
colorScheme.update(mode);
|
|
116
|
+
});
|
|
117
|
+
|
|
99
118
|
/**
|
|
100
119
|
* Helper methods to determining what the user's preferred color scheme is
|
|
101
120
|
* based on the system preferences rather than the users explicit preference.
|
|
102
121
|
*/
|
|
103
122
|
export const prefers = {
|
|
104
|
-
dark: () =>
|
|
105
|
-
light: () =>
|
|
123
|
+
dark: () => queries.dark.matches,
|
|
124
|
+
light: () => queries.light.matches,
|
|
125
|
+
none: () => queries.none.matches,
|
|
106
126
|
custom: (name: string) => window.matchMedia(`(prefers-color-scheme: ${name})`).matches,
|
|
107
|
-
none: () => window.matchMedia('(prefers-color-scheme: no-preference)').matches,
|
|
108
127
|
};
|
|
109
128
|
|
|
110
129
|
const LOCAL_PREF_KEY = 'ember-primitives/color-scheme#local-preference';
|
|
@@ -163,3 +182,5 @@ function styleOf(element?: HTMLElement) {
|
|
|
163
182
|
|
|
164
183
|
return document.documentElement.style;
|
|
165
184
|
}
|
|
185
|
+
|
|
186
|
+
sync();
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { hash } from "@ember/helper";
|
|
2
|
+
|
|
3
|
+
import type { TOC } from "@ember/component/template-only";
|
|
4
|
+
|
|
5
|
+
const Separator: TOC<{
|
|
6
|
+
Element: HTMLSpanElement;
|
|
7
|
+
Blocks: {
|
|
8
|
+
default: [];
|
|
9
|
+
};
|
|
10
|
+
}> = <template>
|
|
11
|
+
<span aria-hidden="true" ...attributes>
|
|
12
|
+
{{yield}}
|
|
13
|
+
</span>
|
|
14
|
+
</template>;
|
|
15
|
+
|
|
16
|
+
export interface Signature {
|
|
17
|
+
Element: HTMLElement;
|
|
18
|
+
Args: {
|
|
19
|
+
/**
|
|
20
|
+
* The accessible label for the breadcrumb navigation.
|
|
21
|
+
* Defaults to "Breadcrumb"
|
|
22
|
+
*/
|
|
23
|
+
label?: string;
|
|
24
|
+
};
|
|
25
|
+
Blocks: {
|
|
26
|
+
default: [
|
|
27
|
+
{
|
|
28
|
+
/**
|
|
29
|
+
* A separator component to place between breadcrumb items.
|
|
30
|
+
* Typically renders as "/" or ">" with aria-hidden="true".
|
|
31
|
+
*/
|
|
32
|
+
Separator: typeof Separator;
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A breadcrumb navigation component that displays the current page's location within a navigational hierarchy.
|
|
40
|
+
*
|
|
41
|
+
* Breadcrumbs help users understand their current location and provide a way to navigate back through the hierarchy.
|
|
42
|
+
*
|
|
43
|
+
* For example:
|
|
44
|
+
*
|
|
45
|
+
* ```gjs live preview
|
|
46
|
+
* import { Breadcrumb } from 'ember-primitives';
|
|
47
|
+
*
|
|
48
|
+
* <template>
|
|
49
|
+
* <Breadcrumb as |b|>
|
|
50
|
+
* <li>
|
|
51
|
+
* <a href="/">Home</a>
|
|
52
|
+
* </li>
|
|
53
|
+
* <b.Separator>/</b.Separator>
|
|
54
|
+
* <li>
|
|
55
|
+
* <a href="/docs">Docs</a>
|
|
56
|
+
* </li>
|
|
57
|
+
* <b.Separator>/</b.Separator>
|
|
58
|
+
* <li aria-current="page">
|
|
59
|
+
* Breadcrumb
|
|
60
|
+
* </li>
|
|
61
|
+
* </Breadcrumb>
|
|
62
|
+
* </template>
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export const Breadcrumb: TOC<Signature> = <template>
|
|
66
|
+
<nav aria-label={{if @label @label "Breadcrumb"}} ...attributes>
|
|
67
|
+
<ol>
|
|
68
|
+
{{yield (hash Separator=Separator)}}
|
|
69
|
+
</ol>
|
|
70
|
+
</nav>
|
|
71
|
+
</template>;
|
|
72
|
+
|
|
73
|
+
export default Breadcrumb;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import Component from "@glimmer/component";
|
|
2
|
+
import { tracked } from "@glimmer/tracking";
|
|
3
|
+
import { assert } from "@ember/debug";
|
|
4
|
+
import { hash } from "@ember/helper";
|
|
5
|
+
import { on } from "@ember/modifier";
|
|
6
|
+
|
|
7
|
+
import { modifier as eModifier } from "ember-modifier";
|
|
8
|
+
// temp
|
|
9
|
+
// https://github.com/tracked-tools/tracked-toolbox/issues/38
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
11
|
+
// @ts-expect-error
|
|
12
|
+
import { localCopy } from "tracked-toolbox";
|
|
13
|
+
|
|
14
|
+
import type { TOC } from "@ember/component/template-only";
|
|
15
|
+
import type { ModifierLike, WithBoundArgs } from "@glint/template";
|
|
16
|
+
|
|
17
|
+
const DrawerElement: TOC<{
|
|
18
|
+
Element: HTMLDialogElement;
|
|
19
|
+
Args: {
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
open: boolean | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
register: ModifierLike<{ Element: HTMLDialogElement }>;
|
|
33
|
+
};
|
|
34
|
+
Blocks: { default: [] };
|
|
35
|
+
}> = <template>
|
|
36
|
+
<dialog ...attributes open={{@open}} {{on "close" @onClose}} {{@register}}>
|
|
37
|
+
{{yield}}
|
|
38
|
+
</dialog>
|
|
39
|
+
</template>;
|
|
40
|
+
|
|
41
|
+
export interface Signature {
|
|
42
|
+
Args: {
|
|
43
|
+
/**
|
|
44
|
+
* Optionally set the open state of the drawer
|
|
45
|
+
* The state will still be managed internally,
|
|
46
|
+
* so this does not need to be a maintained value, but whenever it changes,
|
|
47
|
+
* the drawer element will reflect that change accordingly.
|
|
48
|
+
*/
|
|
49
|
+
open?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* When the drawer is closed, this function will be called
|
|
52
|
+
* and the drawer's `returnValue` will be passed.
|
|
53
|
+
*
|
|
54
|
+
* This can be used to determine which button was clicked to close the drawer
|
|
55
|
+
*
|
|
56
|
+
* Note though that this value is only populated when using
|
|
57
|
+
* `<form method='dialog'>`
|
|
58
|
+
*/
|
|
59
|
+
onClose?: (returnValue: string) => void;
|
|
60
|
+
};
|
|
61
|
+
Blocks: {
|
|
62
|
+
default: [
|
|
63
|
+
{
|
|
64
|
+
/**
|
|
65
|
+
* Represents the open state of the drawer element.
|
|
66
|
+
*/
|
|
67
|
+
isOpen: boolean;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Closes the drawer element
|
|
71
|
+
* Will throw an error if `Drawer` is not rendered.
|
|
72
|
+
*/
|
|
73
|
+
close: () => void;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Opens the drawer element.
|
|
77
|
+
* Will throw an error if `Drawer` is not rendered.
|
|
78
|
+
*/
|
|
79
|
+
open: () => void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* This modifier should be applied to the button that opens the Drawer so that it can be re-focused when the drawer closes.
|
|
83
|
+
*
|
|
84
|
+
* Example:
|
|
85
|
+
*
|
|
86
|
+
* ```gjs
|
|
87
|
+
* <template>
|
|
88
|
+
* <Drawer as |d|>
|
|
89
|
+
* <button {{d.focusOnClose}} {{on "click" d.open}}>Open</button>
|
|
90
|
+
*
|
|
91
|
+
* <d.Drawer>...</d.Drawer>
|
|
92
|
+
* </Drawer>
|
|
93
|
+
* </template>
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
focusOnClose: ModifierLike<{ Element: HTMLElement }>;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* This is the `<dialog>` element (with some defaults pre-wired).
|
|
100
|
+
* This is required to be rendered.
|
|
101
|
+
*/
|
|
102
|
+
Drawer: WithBoundArgs<typeof DrawerElement, "onClose" | "register" | "open">;
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class DrawerDialog extends Component<Signature> {
|
|
109
|
+
<template>
|
|
110
|
+
{{yield
|
|
111
|
+
(hash
|
|
112
|
+
isOpen=this.isOpen
|
|
113
|
+
open=this.open
|
|
114
|
+
close=this.close
|
|
115
|
+
focusOnClose=this.refocus
|
|
116
|
+
Drawer=(component DrawerElement open=@open onClose=this.handleClose register=this.register)
|
|
117
|
+
)
|
|
118
|
+
}}
|
|
119
|
+
</template>
|
|
120
|
+
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
122
|
+
@localCopy("args.open") declare _isOpen: boolean;
|
|
123
|
+
|
|
124
|
+
get isOpen() {
|
|
125
|
+
/**
|
|
126
|
+
* Always fallback to false (closed)
|
|
127
|
+
*/
|
|
128
|
+
return this._isOpen ?? false;
|
|
129
|
+
}
|
|
130
|
+
set isOpen(val: boolean) {
|
|
131
|
+
this._isOpen = val;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#lastIsOpen = false;
|
|
135
|
+
refocus = eModifier((element) => {
|
|
136
|
+
assert(`focusOnClose is only valid on a HTMLElement`, element instanceof HTMLElement);
|
|
137
|
+
|
|
138
|
+
if (!this.isOpen && this.#lastIsOpen) {
|
|
139
|
+
element.focus();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this.#lastIsOpen = this.isOpen;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
@tracked declare drawerElement: HTMLDialogElement | undefined;
|
|
146
|
+
|
|
147
|
+
register = eModifier((element: HTMLDialogElement) => {
|
|
148
|
+
/**
|
|
149
|
+
* This is very sad.
|
|
150
|
+
*
|
|
151
|
+
* But we need the element to be 'root state'
|
|
152
|
+
* so that when we read things like "isOpen",
|
|
153
|
+
* when the drawer is finally rendered, all the
|
|
154
|
+
* downstream properties render.
|
|
155
|
+
*
|
|
156
|
+
* This has to be an async / delayed a bit, so that
|
|
157
|
+
* the tracking frame can exit, and we don't infinite loop
|
|
158
|
+
*/
|
|
159
|
+
void (async () => {
|
|
160
|
+
await Promise.resolve();
|
|
161
|
+
|
|
162
|
+
this.drawerElement = element;
|
|
163
|
+
})();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Closes the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
168
|
+
*/
|
|
169
|
+
close = () => {
|
|
170
|
+
assert(
|
|
171
|
+
"Cannot call `close` on <Drawer> without rendering the drawer element.",
|
|
172
|
+
this.drawerElement,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* If the element is already closed, don't run all this again
|
|
177
|
+
*/
|
|
178
|
+
if (!this.drawerElement.hasAttribute("open")) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* removes the `open` attribute
|
|
184
|
+
* handleClose will be called because the drawer has bound the `close` event.
|
|
185
|
+
*/
|
|
186
|
+
this.drawerElement.close();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @internal
|
|
191
|
+
*
|
|
192
|
+
* handles the <dialog> element's native close behavior.
|
|
193
|
+
* listened to via addEventListener('close', ...);
|
|
194
|
+
*/
|
|
195
|
+
handleClose = () => {
|
|
196
|
+
assert(
|
|
197
|
+
"Cannot call `handleClose` on <Drawer> without rendering the drawer element. This is likely a bug in ember-primitives. Please open an issue <3",
|
|
198
|
+
this.drawerElement,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
this.isOpen = false;
|
|
202
|
+
this.args.onClose?.(this.drawerElement.returnValue);
|
|
203
|
+
// the return value ends up staying... which is annoying
|
|
204
|
+
this.drawerElement.returnValue = "";
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Opens the drawer -- this will throw an error in development if the drawer element was not rendered
|
|
209
|
+
*/
|
|
210
|
+
open = () => {
|
|
211
|
+
assert(
|
|
212
|
+
"Cannot call `open` on <Drawer> without rendering the drawer element.",
|
|
213
|
+
this.drawerElement,
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* If the element is already open, don't run all this again
|
|
218
|
+
*/
|
|
219
|
+
if (this.drawerElement.hasAttribute("open")) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* adds the `open` attribute
|
|
225
|
+
*/
|
|
226
|
+
this.drawerElement.showModal();
|
|
227
|
+
this.isOpen = true;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export const Drawer = DrawerDialog;
|
|
232
|
+
|
|
233
|
+
export default DrawerDialog;
|
package/src/index.ts
CHANGED
|
@@ -19,7 +19,9 @@ export type {
|
|
|
19
19
|
AccordionTriggerExternalSignature,
|
|
20
20
|
} from './components/accordion/public.ts';
|
|
21
21
|
export { Avatar } from './components/avatar.gts';
|
|
22
|
+
export { Breadcrumb } from './components/breadcrumb.gts';
|
|
22
23
|
export { Dialog, Dialog as Modal } from './components/dialog.gts';
|
|
24
|
+
export { Drawer } from './components/drawer.gts';
|
|
23
25
|
export { ExternalLink } from './components/external-link.gts';
|
|
24
26
|
export { Form } from './components/form.gts';
|
|
25
27
|
export { Key, KeyCombo } from './components/keys.gts';
|