ember-primitives 0.28.0 → 0.29.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.
@@ -60,6 +60,24 @@ export interface Signature {
60
60
  * Will throw an error if `Dialog` is not rendered.
61
61
  */
62
62
  open: () => void;
63
+ /**
64
+ * This modifier should be applied to the button that opens the Dialog so that it can be re-focused when the dialog closes.
65
+ *
66
+ * Example:
67
+ *
68
+ * ```gjs
69
+ * <template>
70
+ * <Modal as |m|>
71
+ * <button {{m.focusOnClose}} {{on "click" m.open}}>Open</button>
72
+ *
73
+ * <m.Dialog>...</m.Dialog>
74
+ * </Modal>
75
+ * </template>
76
+ * ```
77
+ */
78
+ focusOnClose: ModifierLike<{
79
+ Element: HTMLElement;
80
+ }>;
63
81
  /**
64
82
  * This is the `<dialog>` element (with some defaults pre-wired).
65
83
  * This is required to be rendered.
@@ -70,9 +88,17 @@ export interface Signature {
70
88
  };
71
89
  }
72
90
  declare class ModalDialog extends Component<Signature> {
91
+ #private;
73
92
  _isOpen: boolean;
74
93
  get isOpen(): boolean;
75
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
+ }>;
76
102
  dialogElement: HTMLDialogElement | undefined;
77
103
  register: import("ember-modifier").FunctionBasedModifier<{
78
104
  Args: {
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/components/dialog.ts"],"names":[],"mappings":"AAAA,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,CAYC,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;gBAChB;;;mBAGG;gBACH,KAAK,EAAE,MAAM,IAAI,CAAC;gBAClB;;;mBAGG;gBACH,IAAI,EAAE,MAAM,IAAI,CAAC;gBACjB;;;mBAGG;gBACH,MAAM,EAAE,aAAa,CAAC,OAAO,aAAa,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC;aAC9E;SACF,CAAC;KACH,CAAC;CACH;AAED,cAAM,WAAY,SAAQ,SAAS,CAAC,SAAS,CAAC;IAYZ,OAAO,EAAE,OAAO,CAAC;IAEjD,IAAI,MAAM,IAMM,OAAO,CADtB;IACD,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,EAEtB;IAEgB,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,KAAK,oBAAc,CAAC;AACjC,eAAO,MAAM,MAAM,oBAAc,CAAC;AAElC,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/components/dialog.ts"],"names":[],"mappings":"AAAA,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,CAYC,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,WAAY,SAAQ,SAAS,CAAC,SAAS,CAAC;;IAaZ,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,KAAK,oBAAc,CAAC;AACjC,eAAO,MAAM,MAAM,oBAAc,CAAC;AAElC,eAAe,WAAW,CAAC"}
@@ -0,0 +1,12 @@
1
+ import "./visually-hidden.css";
2
+ import type { TOC } from "@ember/component/template-only";
3
+ export declare const VisuallyHidden: TOC<{
4
+ Element: HTMLSpanElement;
5
+ Blocks: {
6
+ /**
7
+ * Content to hide visually
8
+ */
9
+ default: [];
10
+ };
11
+ }>;
12
+ //# sourceMappingURL=visually-hidden.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visually-hidden.d.ts","sourceRoot":"","sources":["../../src/components/visually-hidden.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,GAAG,CAAC;IAC/B,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE;QACN;;WAEG;QACH,OAAO,EAAE,EAAE,CAAC;KACb,CAAC;CACH,CAUC,CAAC"}
@@ -19,6 +19,7 @@ export { Shadowed } from './components/shadowed';
19
19
  export { Switch } from './components/switch';
20
20
  export { Toggle } from './components/toggle';
21
21
  export { ToggleGroup } from './components/toggle-group';
22
+ export { VisuallyHidden } from './components/visually-hidden';
22
23
  export { Zoetrope } from './components/zoetrope.ts';
23
24
  export * from './helpers.ts';
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -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,0CAA0C,CAAC;AACzE,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,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,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,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,0CAA0C,CAAC;AACzE,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,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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Styles that are always needed, but their components
3
+ * may not be are included here.
4
+ */
5
+ import './components/visually-hidden.css';
6
+ //# sourceMappingURL=styles.css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.css.d.ts","sourceRoot":"","sources":["../src/styles.css.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,kCAAkC,CAAC"}
@@ -18,7 +18,7 @@ const DialogElement = setComponentTemplate(precompileTemplate("\n <dialog ...at
18
18
  }), templateOnly());
19
19
  class ModalDialog extends Component {
20
20
  static {
21
- setComponentTemplate(precompileTemplate("\n {{yield (hash isOpen=this.isOpen open=this.open close=this.close Dialog=(component DialogElement open=@open onClose=this.handleClose register=this.register))}}\n ", {
21
+ setComponentTemplate(precompileTemplate("\n {{yield (hash isOpen=this.isOpen open=this.open close=this.close focusOnClose=this.refocus Dialog=(component DialogElement open=@open onClose=this.handleClose register=this.register))}}\n ", {
22
22
  strictMode: true,
23
23
  scope: () => ({
24
24
  hash,
@@ -40,6 +40,14 @@ class ModalDialog extends Component {
40
40
  set isOpen(val) {
41
41
  this._isOpen = val;
42
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
+ });
43
51
  static {
44
52
  g(this.prototype, "dialogElement", [tracked]);
45
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.js","sources":["../../src/components/dialog.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 } 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 DialogElement: 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 `<dialog>`\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 dialog element will reflect that change accordingly.\n */\n open?: boolean;\n /**\n * When the `<dialog>` is closed, this function will be called\n * and the `<dialog>`'s `returnValue` will be passed.\n *\n * This can be used to determine which button was clicked to close the modal\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 `<dialog>` element.\n */\n isOpen: boolean;\n /**\n * Closes the `<dialog>` element\n * Will throw an error if `Dialog` is not rendered.\n */\n close: () => void;\n /**\n * Opens the `<dialog>` element.\n * Will throw an error if `Dialog` is not rendered.\n */\n open: () => void;\n /**\n * This is the `<dialog>` element (with some defaults pre-wired).\n * This is required to be rendered.\n */\n Dialog: WithBoundArgs<typeof DialogElement, \"onClose\" | \"register\" | \"open\">;\n },\n ];\n };\n}\n\nclass ModalDialog extends Component<Signature> {\n <template>\n {{yield\n (hash\n isOpen=this.isOpen\n open=this.open\n close=this.close\n Dialog=(component DialogElement 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 @tracked declare dialogElement: HTMLDialogElement | undefined;\n\n register = modifier((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 dialog 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.dialogElement = element;\n })();\n });\n\n /**\n * Closes the dialog -- this will throw an error in development if the dialog element was not rendered\n */\n close = () => {\n assert(\n \"Cannot call `close` on <Dialog> without rendering the dialog element.\",\n this.dialogElement,\n );\n\n /**\n * If the element is already closed, don't run all this again\n */\n if (!this.dialogElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * removes the `open` attribute\n * handleClose will be called because the dialog has bound the `close` event.\n */\n this.dialogElement.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 `handleDialogClose` on <Dialog> without rendering the dialog element. This is likely a bug in ember-primitives. Please open an issue <3\",\n this.dialogElement,\n );\n\n this.isOpen = false;\n this.args.onClose?.(this.dialogElement.returnValue);\n // the return value ends up staying... which is annoying\n this.dialogElement.returnValue = \"\";\n };\n\n /**\n * Opens the dialog -- this will throw an error in development if the dialog element was not rendered\n */\n open = () => {\n assert(\n \"Cannot call `open` on <Dialog> without rendering the dialog element.\",\n this.dialogElement,\n );\n\n /**\n * If the element is already open, don't run all this again\n */\n if (this.dialogElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * adds the `open` attribute\n */\n this.dialogElement.showModal();\n this.isOpen = true;\n };\n}\n\nexport const Modal = ModalDialog;\nexport const Dialog = ModalDialog;\n\nexport default ModalDialog;\n"],"names":["DialogElement","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly","ModalDialog","Component","hash","g","prototype","localCopy","i","void 0","isOpen","_isOpen","val","tracked","register","modifier","element","Promise","resolve","dialogElement","close","assert","hasAttribute","handleClose","args","onClose","returnValue","open","showModal","Modal","Dialog"],"mappings":";;;;;;;;;;;;AAgBA,MAAMA,aAkBD,GAAAC,oBAAA,CAAAC,kBAAA,CAIL,iHAAA,EAAA;EAAAC,UAAA,EAAA,IAAA;AAAAC,EAAAA,KAAA,EAAAA,OAAA;AAAAC,IAAAA;AAAA,GAAA;AAAU,CAAA,CAAA,EAAAC,YAAA,EAAA,CAAA;AAiDV,MAAMC,oBAAoBC,SAAU,CAAA;AAClC,EAAA;IAAAP,oBAAA,CAAAC,kBAAA,CASA,2KAAA,EAAA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;QAAAK,IAAA;AAAAT,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AAEV;AAAA,EAAA;AAAAU,IAAAA,CAAA,MAAAC,SAAA,EAAA,SAAA,EAAA,CACCC,SAAU,CAAA,WAAA,CAAA,CAAA,CAAA;AAAA;AAAA,EAAA,QAAA,IAAAC,CAAA,CAAA,IAAA,EAAA,SAAA,CAAA,EAAAC,MAAA;EAEX,IAAIC,MAASA,GAAA;AACX;;AAEC;AACD,IAAA,OAAO,IAAI,CAACC,OAAO,IAAI,KAAA;AACzB;EACA,IAAID,MAAAA,CAAOE,GAAY,EAAE;IACvB,IAAI,CAACD,OAAO,GAAGC,GAAA;AACjB;AAAA,EAAA;IAAAP,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,eAAA,EAAA,CAECO,OAAA,CAAA,CAAA;AAAA;AAAA,EAAA,cAAA,IAAAL,CAAA,CAAA,IAAA,EAAA,eAAA,CAAA,EAAAC,MAAA;AAEDK,EAAAA,QAAW,GAAAC,QAAA,CAAUC,OAAS,IAAA;AAC5B;;;;;;;;;;AAUC;AACD,IAAA,KAAK,CAAC,YAAA;AACJ,MAAA,MAAMC,QAAQC,OAAO,EAAA;MAErB,IAAI,CAACC,aAAa,GAAGH,OAAA;AACvB,KAAC,GAAA;AACH,GAAG,CAAA;AAEH;;AAEC;EACDI,KAAQ,GAAAA,MAAA;AACNC,IAAAA,MACE,CAAA,uEAAA,EACA,IAAI,CAACF,aAAa,CAAA;AAGpB;;;IAGA,IAAI,CAAC,IAAI,CAACA,aAAa,CAACG,YAAY,CAAC,MAAS,CAAA,EAAA;AAC5C,MAAA;AACF;AAEA;;;AAGC;AACD,IAAA,IAAI,CAACH,aAAa,CAACC,KAAK,EAAA;GACxB;AAEF;;;;;AAKC;EACDG,WAAc,GAAAA,MAAA;AACZF,IAAAA,MACE,CAAA,qJAAA,EACA,IAAI,CAACF,aAAa,CAAA;IAGpB,IAAI,CAACT,MAAM,GAAG,KAAA;IACd,IAAI,CAACc,IAAI,CAACC,OAAO,GAAG,IAAI,CAACN,aAAa,CAACO,WAAW,CAAA;AAClD;AACA,IAAA,IAAI,CAACP,aAAa,CAACO,WAAW,GAAG,EAAA;GACjC;AAEF;;AAEC;EACDC,IAAO,GAAAA,MAAA;AACLN,IAAAA,MACE,CAAA,sEAAA,EACA,IAAI,CAACF,aAAa,CAAA;AAGpB;;AAEC;IACD,IAAI,IAAI,CAACA,aAAa,CAACG,YAAY,CAAC,MAAS,CAAA,EAAA;AAC3C,MAAA;AACF;AAEA;;AAEC;AACD,IAAA,IAAI,CAACH,aAAa,CAACS,SAAS,EAAA;IAC5B,IAAI,CAAClB,MAAM,GAAG,IAAA;GACd;AACJ;AAEO,MAAMmB,QAAQ3B;AACd,MAAM4B,SAAS5B;;;;"}
1
+ {"version":3,"file":"dialog.js","sources":["../../src/components/dialog.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 DialogElement: 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 `<dialog>`\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 dialog element will reflect that change accordingly.\n */\n open?: boolean;\n /**\n * When the `<dialog>` is closed, this function will be called\n * and the `<dialog>`'s `returnValue` will be passed.\n *\n * This can be used to determine which button was clicked to close the modal\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 `<dialog>` element.\n */\n isOpen: boolean;\n\n /**\n * Closes the `<dialog>` element\n * Will throw an error if `Dialog` is not rendered.\n */\n close: () => void;\n\n /**\n * Opens the `<dialog>` element.\n * Will throw an error if `Dialog` is not rendered.\n */\n open: () => void;\n\n /**\n * This modifier should be applied to the button that opens the Dialog so that it can be re-focused when the dialog closes.\n *\n * Example:\n *\n * ```gjs\n * <template>\n * <Modal as |m|>\n * <button {{m.focusOnClose}} {{on \"click\" m.open}}>Open</button>\n *\n * <m.Dialog>...</m.Dialog>\n * </Modal>\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 Dialog: WithBoundArgs<typeof DialogElement, \"onClose\" | \"register\" | \"open\">;\n },\n ];\n };\n}\n\nclass ModalDialog 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 Dialog=(component DialogElement 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 dialogElement: 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 dialog 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.dialogElement = element;\n })();\n });\n\n /**\n * Closes the dialog -- this will throw an error in development if the dialog element was not rendered\n */\n close = () => {\n assert(\n \"Cannot call `close` on <Dialog> without rendering the dialog element.\",\n this.dialogElement,\n );\n\n /**\n * If the element is already closed, don't run all this again\n */\n if (!this.dialogElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * removes the `open` attribute\n * handleClose will be called because the dialog has bound the `close` event.\n */\n this.dialogElement.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 `handleDialogClose` on <Dialog> without rendering the dialog element. This is likely a bug in ember-primitives. Please open an issue <3\",\n this.dialogElement,\n );\n\n this.isOpen = false;\n this.args.onClose?.(this.dialogElement.returnValue);\n // the return value ends up staying... which is annoying\n this.dialogElement.returnValue = \"\";\n };\n\n /**\n * Opens the dialog -- this will throw an error in development if the dialog element was not rendered\n */\n open = () => {\n assert(\n \"Cannot call `open` on <Dialog> without rendering the dialog element.\",\n this.dialogElement,\n );\n\n /**\n * If the element is already open, don't run all this again\n */\n if (this.dialogElement.hasAttribute(\"open\")) {\n return;\n }\n\n /**\n * adds the `open` attribute\n */\n this.dialogElement.showModal();\n this.isOpen = true;\n };\n}\n\nexport const Modal = ModalDialog;\nexport const Dialog = ModalDialog;\n\nexport default ModalDialog;\n"],"names":["DialogElement","setComponentTemplate","precompileTemplate","strictMode","scope","on","templateOnly","ModalDialog","Component","hash","g","prototype","localCopy","i","void 0","isOpen","_isOpen","val","refocus","eModifier","element","assert","HTMLElement","focus","tracked","register","Promise","resolve","dialogElement","close","hasAttribute","handleClose","args","onClose","returnValue","open","showModal","Modal","Dialog"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /* See: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_visually-hidden.scss */
2
+ .ember-primitives__visually-hidden,
3
+ [visually-hidden] {
4
+ position: absolute;
5
+ border: 0;
6
+ width: 1px;
7
+ height: 1px;
8
+ padding: 0;
9
+ margin: -1px;
10
+ overflow: hidden;
11
+ clip: rect(0, 0, 0, 0);
12
+ white-space: nowrap;
13
+ word-wrap: normal;
14
+ }
@@ -0,0 +1,11 @@
1
+ import './visually-hidden.css';
2
+ import { precompileTemplate } from '@ember/template-compilation';
3
+ import { setComponentTemplate } from '@ember/component';
4
+ import templateOnly from '@ember/component/template-only';
5
+
6
+ const VisuallyHidden = setComponentTemplate(precompileTemplate("\n <span class=\"ember-primitives__visually-hidden\" ...attributes>{{yield}}</span>\n", {
7
+ strictMode: true
8
+ }), templateOnly());
9
+
10
+ export { VisuallyHidden };
11
+ //# sourceMappingURL=visually-hidden.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visually-hidden.js","sources":["../../src/components/visually-hidden.gts"],"sourcesContent":["import \"./visually-hidden.css\";\n\nimport type { TOC } from \"@ember/component/template-only\";\n\nexport const VisuallyHidden: TOC<{\n Element: HTMLSpanElement;\n Blocks: {\n /**\n * Content to hide visually\n */\n default: [];\n };\n}> = <template>\n <span class=\"ember-primitives__visually-hidden\" ...attributes>{{yield}}</span>\n</template>;\n"],"names":["VisuallyHidden","setComponentTemplate","precompileTemplate","strictMode","templateOnly"],"mappings":";;;;;MAIaA,cAQR,GAAAC,oBAAA,CAAAC,kBAAA,CAEL,wFAAA,EAAA;EAAAC,UAAA,EAAA;AAAU,CAAE,CAAA,EAAAC,YAAA,EAAA;;;;"}
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ export { Shadowed } from './components/shadowed.js';
19
19
  export { Switch } from './components/switch.js';
20
20
  export { Toggle } from './components/toggle.js';
21
21
  export { ToggleGroup } from './components/toggle-group.js';
22
+ export { VisuallyHidden } from './components/visually-hidden.js';
22
23
  export { Zoetrope } from './components/zoetrope/index.js';
23
24
  export { link } from './helpers/link.js';
24
25
  export { service } from './helpers/service.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/index.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 { 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 { 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"}
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/index.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 { 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"}
@@ -0,0 +1,2 @@
1
+ import './components/visually-hidden.css';
2
+ //# sourceMappingURL=styles.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-primitives",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Making apps easier to build",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -19,7 +19,7 @@
19
19
  "dependencies": {
20
20
  "@babel/runtime": "^7.24.1",
21
21
  "@embroider/addon-shim": "^1.9.0",
22
- "@embroider/macros": "1.16.11",
22
+ "@embroider/macros": "^1.16.11",
23
23
  "@floating-ui/dom": "^1.5.3",
24
24
  "decorator-transforms": "^2.3.0",
25
25
  "ember-element-helper": ">= 0.8.6",
@@ -45,10 +45,10 @@
45
45
  "@embroider/addon-dev": "7.1.3",
46
46
  "@glimmer/component": "^2.0.0",
47
47
  "@glimmer/tracking": "^1.1.2",
48
- "@glint/core": "unstable",
49
- "@glint/environment-ember-loose": "unstable",
50
- "@glint/environment-ember-template-imports": "unstable",
51
- "@glint/template": "unstable",
48
+ "@glint/core": "^1.5.2",
49
+ "@glint/environment-ember-loose": "^1.5.2",
50
+ "@glint/environment-ember-template-imports": "^1.5.2",
51
+ "@glint/template": "^1.5.2",
52
52
  "@nullvoxpopuli/eslint-configs": "^5.1.1",
53
53
  "@rollup/plugin-babel": "^6.0.4",
54
54
  "@tsconfig/ember": "^3.0.5",
@@ -95,6 +95,9 @@
95
95
  "types": "./declarations/*.d.ts",
96
96
  "default": "./dist/*.js"
97
97
  },
98
+ "./*.css": {
99
+ "default": "./dist/*.css"
100
+ },
98
101
  "./test-support": {
99
102
  "types": "./declarations/test-support/index.d.ts",
100
103
  "default": "./dist/test-support/index.js"
@@ -119,7 +122,7 @@
119
122
  "@ember/test-waiters": ">= 3.0.2",
120
123
  "@glimmer/component": ">= 1.1.2",
121
124
  "@glimmer/tracking": ">= 1.1.2",
122
- "@glint/template": ">= 1.3.0",
125
+ "@glint/template": ">= 1.0.0",
123
126
  "ember-modifier": ">= 4.1.0",
124
127
  "ember-resources": ">= 6.1.0",
125
128
  "ember-source": ">= 4.12.0"