@nepdatejs/vanilla 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/dist/auto-define.cjs +1 -1
  3. package/dist/auto-define.js +1 -1
  4. package/dist/{date-picker-ucoEFnMW.js → date-picker-BwlrlU5Y.js} +13 -30
  5. package/dist/date-picker-BwlrlU5Y.js.map +1 -0
  6. package/dist/{date-picker-CQoabjlj.cjs → date-picker-CgjYsf1w.cjs} +12 -29
  7. package/dist/date-picker-CgjYsf1w.cjs.map +1 -0
  8. package/dist/date-picker.cjs +1 -1
  9. package/dist/date-picker.js +1 -1
  10. package/dist/{date-range-picker-DAkCzVgT.js → date-range-picker-NwetXUC-.js} +13 -30
  11. package/dist/date-range-picker-NwetXUC-.js.map +1 -0
  12. package/dist/{date-range-picker-BQKcZeqG.cjs → date-range-picker-VrQZFZED.cjs} +12 -29
  13. package/dist/date-range-picker-VrQZFZED.cjs.map +1 -0
  14. package/dist/date-range-picker.cjs +1 -1
  15. package/dist/date-range-picker.js +1 -1
  16. package/dist/{date-time-picker-Bxfn-a9T.cjs → date-time-picker-ChHIBTBw.cjs} +12 -30
  17. package/dist/date-time-picker-ChHIBTBw.cjs.map +1 -0
  18. package/dist/{date-time-picker-BqweOP2u.js → date-time-picker-CxqC95aM.js} +12 -30
  19. package/dist/date-time-picker-CxqC95aM.js.map +1 -0
  20. package/dist/date-time-picker.cjs +1 -1
  21. package/dist/date-time-picker.js +1 -1
  22. package/dist/{define-DTTdLfIM.cjs → define-BbTIFHtH.cjs} +5 -5
  23. package/dist/{define-DTTdLfIM.cjs.map → define-BbTIFHtH.cjs.map} +1 -1
  24. package/dist/{define-7natoEH4.js → define-D96w8Zu2.js} +5 -5
  25. package/dist/{define-7natoEH4.js.map → define-D96w8Zu2.js.map} +1 -1
  26. package/dist/index.cjs +5 -5
  27. package/dist/index.js +5 -5
  28. package/dist/{multi-date-picker-XCg8Y0sF.js → multi-date-picker-C3Lr0Dq-.js} +13 -28
  29. package/dist/multi-date-picker-C3Lr0Dq-.js.map +1 -0
  30. package/dist/{multi-date-picker-BMEYUPBa.cjs → multi-date-picker-DUyuO-nH.cjs} +12 -27
  31. package/dist/multi-date-picker-DUyuO-nH.cjs.map +1 -0
  32. package/dist/multi-date-picker.cjs +1 -1
  33. package/dist/multi-date-picker.js +1 -1
  34. package/dist/nepdate-picker.global.js +2 -2
  35. package/dist/nepdate-picker.global.js.map +1 -1
  36. package/dist/preset-list-BYCZm61I.cjs +97 -0
  37. package/dist/preset-list-BYCZm61I.cjs.map +1 -0
  38. package/dist/preset-list-DmE6fJjr.js +80 -0
  39. package/dist/preset-list-DmE6fJjr.js.map +1 -0
  40. package/package.json +4 -4
  41. package/src/datetime-view.ts +12 -37
  42. package/src/multi-view.ts +11 -33
  43. package/src/panel.ts +61 -0
  44. package/src/picker-view.ts +11 -36
  45. package/src/range-view.ts +12 -37
  46. package/dist/date-picker-CQoabjlj.cjs.map +0 -1
  47. package/dist/date-picker-ucoEFnMW.js.map +0 -1
  48. package/dist/date-range-picker-BQKcZeqG.cjs.map +0 -1
  49. package/dist/date-range-picker-DAkCzVgT.js.map +0 -1
  50. package/dist/date-time-picker-BqweOP2u.js.map +0 -1
  51. package/dist/date-time-picker-Bxfn-a9T.cjs.map +0 -1
  52. package/dist/multi-date-picker-BMEYUPBa.cjs.map +0 -1
  53. package/dist/multi-date-picker-XCg8Y0sF.js.map +0 -1
  54. package/dist/preset-list-CASwnwmS.js +0 -45
  55. package/dist/preset-list-CASwnwmS.js.map +0 -1
  56. package/dist/preset-list-Cs8H12Wp.cjs +0 -50
  57. package/dist/preset-list-Cs8H12Wp.cjs.map +0 -1
@@ -0,0 +1,97 @@
1
+ const require_registry = require("./registry-3qzdVB7H.cjs");
2
+ let _nepdatejs_dom = require("@nepdatejs/dom");
3
+ //#region src/panel.ts
4
+ /** Show a panel beside its anchor, and close it the usual ways. Returns the way to undo that. */
5
+ function openPanel(options) {
6
+ const { panel, close } = options;
7
+ panel.hidden = false;
8
+ const stopTracking = (0, _nepdatejs_dom.trackPosition)(options.anchor, panel, {
9
+ width: options.width,
10
+ layout: options.layout
11
+ });
12
+ const stopOutside = (0, _nepdatejs_dom.onOutsidePointer)(options.inside, close);
13
+ const stopBackdrop = (0, _nepdatejs_dom.onBackdropPointer)(panel, close);
14
+ const stopEscape = (0, _nepdatejs_dom.onEscape)(() => {
15
+ close();
16
+ (0, _nepdatejs_dom.restoreFocus)(options.returnFocus);
17
+ });
18
+ return () => {
19
+ stopTracking();
20
+ stopOutside();
21
+ stopBackdrop();
22
+ stopEscape();
23
+ panel.hidden = true;
24
+ };
25
+ }
26
+ /** The BS/AD buttons in a panel's footer. */
27
+ function renderSegment(segment, state, locale) {
28
+ segment.hidden = !state.canSwitchCalendar;
29
+ require_registry.setAttrs(segment, { "aria-label": locale.labels.calendar });
30
+ for (const button of segment.querySelectorAll("button")) {
31
+ const calendar = button.dataset["calendar"] === "AD" ? "AD" : "BS";
32
+ require_registry.setText(button, locale.calendarNames[calendar]);
33
+ require_registry.setAttrs(button, { "aria-pressed": String(calendar === state.calendar) });
34
+ }
35
+ }
36
+ //#endregion
37
+ //#region src/preset-list.ts
38
+ /** The shortcut buttons beside the calendar. Hidden when there are none. */
39
+ var PresetList = class {
40
+ constructor(onApply) {
41
+ this.ids = "";
42
+ this.element = require_registry.el("div", {
43
+ class: "ndp-presets",
44
+ role: "group",
45
+ hidden: true
46
+ });
47
+ this.element.addEventListener("click", (event) => {
48
+ const button = event.target instanceof Element ? event.target.closest(".ndp-preset") : null;
49
+ const id = button?.dataset["preset"];
50
+ if (id !== void 0 && button && !button.disabled) onApply(id);
51
+ });
52
+ }
53
+ render(presets, label) {
54
+ this.element.hidden = presets.length === 0;
55
+ require_registry.setAttrs(this.element, { "aria-label": label });
56
+ const ids = presets.map((preset) => preset.id).join("\n");
57
+ if (ids !== this.ids) {
58
+ this.ids = ids;
59
+ this.element.replaceChildren(...presets.map((preset) => require_registry.el("button", {
60
+ type: "button",
61
+ class: "ndp-preset",
62
+ "data-preset": preset.id
63
+ })));
64
+ }
65
+ presets.forEach((preset, index) => {
66
+ const button = this.element.children[index];
67
+ if (button) {
68
+ require_registry.setText(button, preset.label);
69
+ require_registry.setAttrs(button, {
70
+ "aria-pressed": preset.isActive ? "true" : "false",
71
+ disabled: preset.isDisabled
72
+ });
73
+ }
74
+ });
75
+ }
76
+ };
77
+ //#endregion
78
+ Object.defineProperty(exports, "PresetList", {
79
+ enumerable: true,
80
+ get: function() {
81
+ return PresetList;
82
+ }
83
+ });
84
+ Object.defineProperty(exports, "openPanel", {
85
+ enumerable: true,
86
+ get: function() {
87
+ return openPanel;
88
+ }
89
+ });
90
+ Object.defineProperty(exports, "renderSegment", {
91
+ enumerable: true,
92
+ get: function() {
93
+ return renderSegment;
94
+ }
95
+ });
96
+
97
+ //# sourceMappingURL=preset-list-BYCZm61I.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset-list-BYCZm61I.cjs","names":["trackPosition","onOutsidePointer","onBackdropPointer","onEscape","el"],"sources":["../src/panel.ts","../src/preset-list.ts"],"sourcesContent":["import type { CalendarSystem, LocaleData } from '@nepdatejs/core';\nimport {\n onBackdropPointer,\n onEscape,\n onOutsidePointer,\n restoreFocus,\n trackPosition,\n type PanelLayout,\n} from '@nepdatejs/dom';\nimport { setAttrs, setText } from './dom';\n\ninterface OpenPanel {\n readonly panel: HTMLElement;\n readonly anchor: Element;\n /** A pointer down outside these closes the panel. */\n readonly inside: readonly Element[];\n readonly width: number;\n readonly layout: PanelLayout | undefined;\n readonly close: () => void;\n /** Gets focus back after Escape. */\n readonly returnFocus: HTMLElement;\n}\n\n/** Show a panel beside its anchor, and close it the usual ways. Returns the way to undo that. */\nexport function openPanel(options: OpenPanel): () => void {\n const { panel, close } = options;\n panel.hidden = false;\n const stopTracking = trackPosition(options.anchor, panel, {\n width: options.width,\n layout: options.layout,\n });\n const stopOutside = onOutsidePointer(options.inside, close);\n const stopBackdrop = onBackdropPointer(panel, close);\n const stopEscape = onEscape(() => {\n close();\n restoreFocus(options.returnFocus);\n });\n\n return () => {\n stopTracking();\n stopOutside();\n stopBackdrop();\n stopEscape();\n panel.hidden = true;\n };\n}\n\n/** The BS/AD buttons in a panel's footer. */\nexport function renderSegment(\n segment: HTMLElement,\n state: { readonly canSwitchCalendar: boolean; readonly calendar: CalendarSystem },\n locale: LocaleData,\n): void {\n segment.hidden = !state.canSwitchCalendar;\n setAttrs(segment, { 'aria-label': locale.labels.calendar });\n for (const button of segment.querySelectorAll<HTMLButtonElement>('button')) {\n const calendar = button.dataset['calendar'] === 'AD' ? 'AD' : 'BS';\n setText(button, locale.calendarNames[calendar]);\n setAttrs(button, { 'aria-pressed': String(calendar === state.calendar) });\n }\n}\n","import type { PresetState } from '@nepdatejs/datepicker';\nimport { el, setAttrs, setText } from './dom';\n\n/** Panel width with and without the presets column. */\nexport const PANEL_WIDTH = 320;\nexport const PANEL_WIDTH_WITH_PRESETS = 492;\nexport const TIME_COLUMNS_WIDTH = 136;\n\n/** The shortcut buttons beside the calendar. Hidden when there are none. */\nexport class PresetList {\n readonly element: HTMLDivElement;\n private ids = '';\n\n constructor(onApply: (id: string) => void) {\n this.element = el('div', { class: 'ndp-presets', role: 'group', hidden: true });\n this.element.addEventListener('click', (event) => {\n const button =\n event.target instanceof Element\n ? event.target.closest<HTMLButtonElement>('.ndp-preset')\n : null;\n const id = button?.dataset['preset'];\n if (id !== undefined && button && !button.disabled) {\n onApply(id);\n }\n });\n }\n\n render(presets: readonly PresetState[], label: string): void {\n this.element.hidden = presets.length === 0;\n setAttrs(this.element, { 'aria-label': label });\n const ids = presets.map((preset) => preset.id).join('\\n');\n if (ids !== this.ids) {\n this.ids = ids;\n this.element.replaceChildren(\n ...presets.map((preset) =>\n el('button', { type: 'button', class: 'ndp-preset', 'data-preset': preset.id }),\n ),\n );\n }\n presets.forEach((preset, index) => {\n const button = this.element.children[index];\n if (button) {\n setText(button, preset.label);\n setAttrs(button, {\n 'aria-pressed': preset.isActive ? 'true' : 'false',\n disabled: preset.isDisabled,\n });\n }\n });\n }\n}\n"],"mappings":";;;;AAwBA,SAAgB,UAAU,SAAgC;CACxD,MAAM,EAAE,OAAO,UAAU;CACzB,MAAM,SAAS;CACf,MAAM,gBAAA,GAAeA,eAAAA,cAAAA,CAAc,QAAQ,QAAQ,OAAO;EACxD,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB,CAAC;CACD,MAAM,eAAA,GAAcC,eAAAA,iBAAAA,CAAiB,QAAQ,QAAQ,KAAK;CAC1D,MAAM,gBAAA,GAAeC,eAAAA,kBAAAA,CAAkB,OAAO,KAAK;CACnD,MAAM,cAAA,GAAaC,eAAAA,SAAAA,OAAe;EAChC,MAAM;EACN,CAAA,GAAA,eAAA,aAAA,CAAa,QAAQ,WAAW;CAClC,CAAC;CAED,aAAa;EACX,aAAa;EACb,YAAY;EACZ,aAAa;EACb,WAAW;EACX,MAAM,SAAS;CACjB;AACF;;AAGA,SAAgB,cACd,SACA,OACA,QACM;CACN,QAAQ,SAAS,CAAC,MAAM;CACxB,iBAAA,SAAS,SAAS,EAAE,cAAc,OAAO,OAAO,SAAS,CAAC;CAC1D,KAAK,MAAM,UAAU,QAAQ,iBAAoC,QAAQ,GAAG;EAC1E,MAAM,WAAW,OAAO,QAAQ,gBAAgB,OAAO,OAAO;EAC9D,iBAAA,QAAQ,QAAQ,OAAO,cAAc,SAAS;EAC9C,iBAAA,SAAS,QAAQ,EAAE,gBAAgB,OAAO,aAAa,MAAM,QAAQ,EAAE,CAAC;CAC1E;AACF;;;;ACnDA,IAAa,aAAb,MAAwB;CAItB,YAAY,SAA+B;EAF3C,KAAQ,MAAM;EAGZ,KAAK,UAAUC,iBAAAA,GAAG,OAAO;GAAE,OAAO;GAAe,MAAM;GAAS,QAAQ;EAAK,CAAC;EAC9E,KAAK,QAAQ,iBAAiB,UAAU,UAAU;GAChD,MAAM,SACJ,MAAM,kBAAkB,UACpB,MAAM,OAAO,QAA2B,aAAa,IACrD;GACN,MAAM,KAAK,QAAQ,QAAQ;GAC3B,IAAI,OAAO,KAAA,KAAa,UAAU,CAAC,OAAO,UACxC,QAAQ,EAAE;EAEd,CAAC;CACH;CAEA,OAAO,SAAiC,OAAqB;EAC3D,KAAK,QAAQ,SAAS,QAAQ,WAAW;EACzC,iBAAA,SAAS,KAAK,SAAS,EAAE,cAAc,MAAM,CAAC;EAC9C,MAAM,MAAM,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI;EACxD,IAAI,QAAQ,KAAK,KAAK;GACpB,KAAK,MAAM;GACX,KAAK,QAAQ,gBACX,GAAG,QAAQ,KAAK,WACdA,iBAAAA,GAAG,UAAU;IAAE,MAAM;IAAU,OAAO;IAAc,eAAe,OAAO;GAAG,CAAC,CAChF,CACF;EACF;EACA,QAAQ,SAAS,QAAQ,UAAU;GACjC,MAAM,SAAS,KAAK,QAAQ,SAAS;GACrC,IAAI,QAAQ;IACV,iBAAA,QAAQ,QAAQ,OAAO,KAAK;IAC5B,iBAAA,SAAS,QAAQ;KACf,gBAAgB,OAAO,WAAW,SAAS;KAC3C,UAAU,OAAO;IACnB,CAAC;GACH;EACF,CAAC;CACH;AACF"}
@@ -0,0 +1,80 @@
1
+ import { b as setText, g as el, v as setAttrs } from "./registry-BvkGnkvV.js";
2
+ import { onBackdropPointer, onEscape, onOutsidePointer, restoreFocus, trackPosition } from "@nepdatejs/dom";
3
+ //#region src/panel.ts
4
+ /** Show a panel beside its anchor, and close it the usual ways. Returns the way to undo that. */
5
+ function openPanel(options) {
6
+ const { panel, close } = options;
7
+ panel.hidden = false;
8
+ const stopTracking = trackPosition(options.anchor, panel, {
9
+ width: options.width,
10
+ layout: options.layout
11
+ });
12
+ const stopOutside = onOutsidePointer(options.inside, close);
13
+ const stopBackdrop = onBackdropPointer(panel, close);
14
+ const stopEscape = onEscape(() => {
15
+ close();
16
+ restoreFocus(options.returnFocus);
17
+ });
18
+ return () => {
19
+ stopTracking();
20
+ stopOutside();
21
+ stopBackdrop();
22
+ stopEscape();
23
+ panel.hidden = true;
24
+ };
25
+ }
26
+ /** The BS/AD buttons in a panel's footer. */
27
+ function renderSegment(segment, state, locale) {
28
+ segment.hidden = !state.canSwitchCalendar;
29
+ setAttrs(segment, { "aria-label": locale.labels.calendar });
30
+ for (const button of segment.querySelectorAll("button")) {
31
+ const calendar = button.dataset["calendar"] === "AD" ? "AD" : "BS";
32
+ setText(button, locale.calendarNames[calendar]);
33
+ setAttrs(button, { "aria-pressed": String(calendar === state.calendar) });
34
+ }
35
+ }
36
+ //#endregion
37
+ //#region src/preset-list.ts
38
+ /** The shortcut buttons beside the calendar. Hidden when there are none. */
39
+ var PresetList = class {
40
+ constructor(onApply) {
41
+ this.ids = "";
42
+ this.element = el("div", {
43
+ class: "ndp-presets",
44
+ role: "group",
45
+ hidden: true
46
+ });
47
+ this.element.addEventListener("click", (event) => {
48
+ const button = event.target instanceof Element ? event.target.closest(".ndp-preset") : null;
49
+ const id = button?.dataset["preset"];
50
+ if (id !== void 0 && button && !button.disabled) onApply(id);
51
+ });
52
+ }
53
+ render(presets, label) {
54
+ this.element.hidden = presets.length === 0;
55
+ setAttrs(this.element, { "aria-label": label });
56
+ const ids = presets.map((preset) => preset.id).join("\n");
57
+ if (ids !== this.ids) {
58
+ this.ids = ids;
59
+ this.element.replaceChildren(...presets.map((preset) => el("button", {
60
+ type: "button",
61
+ class: "ndp-preset",
62
+ "data-preset": preset.id
63
+ })));
64
+ }
65
+ presets.forEach((preset, index) => {
66
+ const button = this.element.children[index];
67
+ if (button) {
68
+ setText(button, preset.label);
69
+ setAttrs(button, {
70
+ "aria-pressed": preset.isActive ? "true" : "false",
71
+ disabled: preset.isDisabled
72
+ });
73
+ }
74
+ });
75
+ }
76
+ };
77
+ //#endregion
78
+ export { openPanel as n, renderSegment as r, PresetList as t };
79
+
80
+ //# sourceMappingURL=preset-list-DmE6fJjr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset-list-DmE6fJjr.js","names":[],"sources":["../src/panel.ts","../src/preset-list.ts"],"sourcesContent":["import type { CalendarSystem, LocaleData } from '@nepdatejs/core';\nimport {\n onBackdropPointer,\n onEscape,\n onOutsidePointer,\n restoreFocus,\n trackPosition,\n type PanelLayout,\n} from '@nepdatejs/dom';\nimport { setAttrs, setText } from './dom';\n\ninterface OpenPanel {\n readonly panel: HTMLElement;\n readonly anchor: Element;\n /** A pointer down outside these closes the panel. */\n readonly inside: readonly Element[];\n readonly width: number;\n readonly layout: PanelLayout | undefined;\n readonly close: () => void;\n /** Gets focus back after Escape. */\n readonly returnFocus: HTMLElement;\n}\n\n/** Show a panel beside its anchor, and close it the usual ways. Returns the way to undo that. */\nexport function openPanel(options: OpenPanel): () => void {\n const { panel, close } = options;\n panel.hidden = false;\n const stopTracking = trackPosition(options.anchor, panel, {\n width: options.width,\n layout: options.layout,\n });\n const stopOutside = onOutsidePointer(options.inside, close);\n const stopBackdrop = onBackdropPointer(panel, close);\n const stopEscape = onEscape(() => {\n close();\n restoreFocus(options.returnFocus);\n });\n\n return () => {\n stopTracking();\n stopOutside();\n stopBackdrop();\n stopEscape();\n panel.hidden = true;\n };\n}\n\n/** The BS/AD buttons in a panel's footer. */\nexport function renderSegment(\n segment: HTMLElement,\n state: { readonly canSwitchCalendar: boolean; readonly calendar: CalendarSystem },\n locale: LocaleData,\n): void {\n segment.hidden = !state.canSwitchCalendar;\n setAttrs(segment, { 'aria-label': locale.labels.calendar });\n for (const button of segment.querySelectorAll<HTMLButtonElement>('button')) {\n const calendar = button.dataset['calendar'] === 'AD' ? 'AD' : 'BS';\n setText(button, locale.calendarNames[calendar]);\n setAttrs(button, { 'aria-pressed': String(calendar === state.calendar) });\n }\n}\n","import type { PresetState } from '@nepdatejs/datepicker';\nimport { el, setAttrs, setText } from './dom';\n\n/** Panel width with and without the presets column. */\nexport const PANEL_WIDTH = 320;\nexport const PANEL_WIDTH_WITH_PRESETS = 492;\nexport const TIME_COLUMNS_WIDTH = 136;\n\n/** The shortcut buttons beside the calendar. Hidden when there are none. */\nexport class PresetList {\n readonly element: HTMLDivElement;\n private ids = '';\n\n constructor(onApply: (id: string) => void) {\n this.element = el('div', { class: 'ndp-presets', role: 'group', hidden: true });\n this.element.addEventListener('click', (event) => {\n const button =\n event.target instanceof Element\n ? event.target.closest<HTMLButtonElement>('.ndp-preset')\n : null;\n const id = button?.dataset['preset'];\n if (id !== undefined && button && !button.disabled) {\n onApply(id);\n }\n });\n }\n\n render(presets: readonly PresetState[], label: string): void {\n this.element.hidden = presets.length === 0;\n setAttrs(this.element, { 'aria-label': label });\n const ids = presets.map((preset) => preset.id).join('\\n');\n if (ids !== this.ids) {\n this.ids = ids;\n this.element.replaceChildren(\n ...presets.map((preset) =>\n el('button', { type: 'button', class: 'ndp-preset', 'data-preset': preset.id }),\n ),\n );\n }\n presets.forEach((preset, index) => {\n const button = this.element.children[index];\n if (button) {\n setText(button, preset.label);\n setAttrs(button, {\n 'aria-pressed': preset.isActive ? 'true' : 'false',\n disabled: preset.isDisabled,\n });\n }\n });\n }\n}\n"],"mappings":";;;;AAwBA,SAAgB,UAAU,SAAgC;CACxD,MAAM,EAAE,OAAO,UAAU;CACzB,MAAM,SAAS;CACf,MAAM,eAAe,cAAc,QAAQ,QAAQ,OAAO;EACxD,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB,CAAC;CACD,MAAM,cAAc,iBAAiB,QAAQ,QAAQ,KAAK;CAC1D,MAAM,eAAe,kBAAkB,OAAO,KAAK;CACnD,MAAM,aAAa,eAAe;EAChC,MAAM;EACN,aAAa,QAAQ,WAAW;CAClC,CAAC;CAED,aAAa;EACX,aAAa;EACb,YAAY;EACZ,aAAa;EACb,WAAW;EACX,MAAM,SAAS;CACjB;AACF;;AAGA,SAAgB,cACd,SACA,OACA,QACM;CACN,QAAQ,SAAS,CAAC,MAAM;CACxB,SAAS,SAAS,EAAE,cAAc,OAAO,OAAO,SAAS,CAAC;CAC1D,KAAK,MAAM,UAAU,QAAQ,iBAAoC,QAAQ,GAAG;EAC1E,MAAM,WAAW,OAAO,QAAQ,gBAAgB,OAAO,OAAO;EAC9D,QAAQ,QAAQ,OAAO,cAAc,SAAS;EAC9C,SAAS,QAAQ,EAAE,gBAAgB,OAAO,aAAa,MAAM,QAAQ,EAAE,CAAC;CAC1E;AACF;;;;ACnDA,IAAa,aAAb,MAAwB;CAItB,YAAY,SAA+B;EAF3C,KAAQ,MAAM;EAGZ,KAAK,UAAU,GAAG,OAAO;GAAE,OAAO;GAAe,MAAM;GAAS,QAAQ;EAAK,CAAC;EAC9E,KAAK,QAAQ,iBAAiB,UAAU,UAAU;GAChD,MAAM,SACJ,MAAM,kBAAkB,UACpB,MAAM,OAAO,QAA2B,aAAa,IACrD;GACN,MAAM,KAAK,QAAQ,QAAQ;GAC3B,IAAI,OAAO,KAAA,KAAa,UAAU,CAAC,OAAO,UACxC,QAAQ,EAAE;EAEd,CAAC;CACH;CAEA,OAAO,SAAiC,OAAqB;EAC3D,KAAK,QAAQ,SAAS,QAAQ,WAAW;EACzC,SAAS,KAAK,SAAS,EAAE,cAAc,MAAM,CAAC;EAC9C,MAAM,MAAM,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI;EACxD,IAAI,QAAQ,KAAK,KAAK;GACpB,KAAK,MAAM;GACX,KAAK,QAAQ,gBACX,GAAG,QAAQ,KAAK,WACd,GAAG,UAAU;IAAE,MAAM;IAAU,OAAO;IAAc,eAAe,OAAO;GAAG,CAAC,CAChF,CACF;EACF;EACA,QAAQ,SAAS,QAAQ,UAAU;GACjC,MAAM,SAAS,KAAK,QAAQ,SAAS;GACrC,IAAI,QAAQ;IACV,QAAQ,QAAQ,OAAO,KAAK;IAC5B,SAAS,QAAQ;KACf,gBAAgB,OAAO,WAAW,SAAS;KAC3C,UAAU,OAAO;IACnB,CAAC;GACH;EACF,CAAC;CACH;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nepdatejs/vanilla",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Nepali BS/AD date picker and calendar as Web Components and a plain JavaScript API.",
5
5
  "keywords": [
6
6
  "nepali",
@@ -126,10 +126,10 @@
126
126
  "node": ">=18"
127
127
  },
128
128
  "dependencies": {
129
- "@nepdatejs/core": "^0.1.0",
129
+ "@nepdatejs/core": "^0.1.1",
130
130
  "@nepdatejs/calendar": "^0.1.0",
131
- "@nepdatejs/datepicker": "^0.1.0",
132
- "@nepdatejs/dom": "^0.1.0",
131
+ "@nepdatejs/datepicker": "^0.1.1",
132
+ "@nepdatejs/dom": "^0.1.1",
133
133
  "@nepdatejs/styles": "^0.1.0"
134
134
  },
135
135
  "publishConfig": {
@@ -1,4 +1,4 @@
1
- import { getLocale, type CalendarSystem } from '@nepdatejs/core';
1
+ import { getLocale } from '@nepdatejs/core';
2
2
  import {
3
3
  createDateTimePicker,
4
4
  type DateTimePickerOptions,
@@ -6,15 +6,9 @@ import {
6
6
  type DateTimePickerStore,
7
7
  type TimeCell,
8
8
  } from '@nepdatejs/datepicker';
9
- import {
10
- onBackdropPointer,
11
- onEscape,
12
- onOutsidePointer,
13
- restoreFocus,
14
- trackPosition,
15
- type PanelLayout,
16
- } from '@nepdatejs/dom';
9
+ import type { PanelLayout } from '@nepdatejs/dom';
17
10
  import { CalendarView } from './calendar-view';
11
+ import { openPanel, renderSegment } from './panel';
18
12
  import { el, icon, setAttrs, setPopupMode, setText, uid } from './dom';
19
13
  import type { Theme } from './picker-view';
20
14
  import {
@@ -297,15 +291,7 @@ export class DateTimePickerView {
297
291
  setText(this.hint, hint ?? '');
298
292
  setAttrs(this.hint, { 'data-error': state.error !== null });
299
293
 
300
- this.segment.hidden = !state.canSwitchCalendar;
301
- setAttrs(this.segment, { 'aria-label': locale.labels.calendar });
302
- for (const button of this.segment.querySelectorAll<HTMLButtonElement>('button')) {
303
- const calendar = button.dataset['calendar'] as CalendarSystem;
304
- setText(button, locale.calendarNames[calendar]);
305
- setAttrs(button, {
306
- 'aria-pressed': calendar === state.calendar ? 'true' : 'false',
307
- });
308
- }
294
+ renderSegment(this.segment, state, locale);
309
295
  setText(this.nowButton, locale.labels.now);
310
296
  setText(this.doneButton, locale.labels.done);
311
297
  setAttrs(this.time, { 'aria-label': locale.labels.time });
@@ -343,28 +329,17 @@ export class DateTimePickerView {
343
329
  this.wasOpen = open;
344
330
  this.options.onOpenChange?.(open);
345
331
  if (open) {
346
- this.panel.hidden = false;
347
- const stopTracking = trackPosition(this.row, this.panel, {
332
+ this.closePanel = openPanel({
333
+ panel: this.panel,
334
+ anchor: this.row,
335
+ inside: [this.field],
348
336
  width: this.panelWidth(),
349
337
  layout: this.options.panelLayout,
338
+ close: () => {
339
+ this.store.actions.close();
340
+ },
341
+ returnFocus: this.dateInput,
350
342
  });
351
- const stopOutside = onOutsidePointer([this.field], () => {
352
- this.store.actions.close();
353
- });
354
- const stopBackdrop = onBackdropPointer(this.panel, () => {
355
- this.store.actions.close();
356
- });
357
- const stopEscape = onEscape(() => {
358
- this.store.actions.close();
359
- restoreFocus(this.dateInput);
360
- });
361
- this.closePanel = () => {
362
- stopTracking();
363
- stopOutside();
364
- stopBackdrop();
365
- stopEscape();
366
- this.panel.hidden = true;
367
- };
368
343
  for (const item of this.time.querySelectorAll<HTMLElement>(
369
344
  '[aria-pressed="true"]',
370
345
  )) {
package/src/multi-view.ts CHANGED
@@ -5,15 +5,9 @@ import {
5
5
  type MultiDatePickerState,
6
6
  type MultiDatePickerStore,
7
7
  } from '@nepdatejs/datepicker';
8
- import {
9
- onBackdropPointer,
10
- onEscape,
11
- onOutsidePointer,
12
- restoreFocus,
13
- trackPosition,
14
- type PanelLayout,
15
- } from '@nepdatejs/dom';
8
+ import { restoreFocus, type PanelLayout } from '@nepdatejs/dom';
16
9
  import { CalendarView } from './calendar-view';
10
+ import { openPanel, renderSegment } from './panel';
17
11
  import { el, icon, setAttrs, setPopupMode, setText, uid } from './dom';
18
12
  import type { Theme } from './picker-view';
19
13
  import { PANEL_WIDTH } from './preset-list';
@@ -235,13 +229,7 @@ export class MultiDatePickerView {
235
229
  this.hint.hidden = state.error === null;
236
230
  setText(this.hint, state.error?.message ?? '');
237
231
 
238
- this.segment.hidden = !state.canSwitchCalendar;
239
- setAttrs(this.segment, { 'aria-label': locale.labels.calendar });
240
- for (const button of this.segment.querySelectorAll<HTMLButtonElement>('button')) {
241
- const calendar = button.dataset['calendar'] === 'AD' ? 'AD' : 'BS';
242
- setText(button, locale.calendarNames[calendar]);
243
- setAttrs(button, { 'aria-pressed': String(calendar === state.calendar) });
244
- }
232
+ renderSegment(this.segment, state, locale);
245
233
  setText(this.doneButton, locale.labels.done);
246
234
  this.doneButton.hidden = state.inline;
247
235
 
@@ -270,27 +258,17 @@ export class MultiDatePickerView {
270
258
  this.wasOpen = open;
271
259
  this.options.onOpenChange?.(open);
272
260
  if (open) {
273
- this.panel.hidden = false;
274
- const stopTracking = trackPosition(this.box, this.panel, {
261
+ this.closePanel = openPanel({
262
+ panel: this.panel,
263
+ anchor: this.box,
264
+ inside: [this.field, this.panel],
275
265
  width: PANEL_WIDTH,
276
266
  layout: this.options.panelLayout,
267
+ close: () => {
268
+ this.store.actions.close();
269
+ },
270
+ returnFocus: this.input,
277
271
  });
278
- const close = (): void => {
279
- this.store.actions.close();
280
- };
281
- const stopOutside = onOutsidePointer([this.field, this.panel], close);
282
- const stopBackdrop = onBackdropPointer(this.panel, close);
283
- const stopEscape = onEscape(() => {
284
- close();
285
- restoreFocus(this.input);
286
- });
287
- this.closePanel = () => {
288
- stopTracking();
289
- stopOutside();
290
- stopBackdrop();
291
- stopEscape();
292
- this.panel.hidden = true;
293
- };
294
272
  this.calendarView.focusGrid();
295
273
  } else {
296
274
  this.closePanel?.();
package/src/panel.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type { CalendarSystem, LocaleData } from '@nepdatejs/core';
2
+ import {
3
+ onBackdropPointer,
4
+ onEscape,
5
+ onOutsidePointer,
6
+ restoreFocus,
7
+ trackPosition,
8
+ type PanelLayout,
9
+ } from '@nepdatejs/dom';
10
+ import { setAttrs, setText } from './dom';
11
+
12
+ interface OpenPanel {
13
+ readonly panel: HTMLElement;
14
+ readonly anchor: Element;
15
+ /** A pointer down outside these closes the panel. */
16
+ readonly inside: readonly Element[];
17
+ readonly width: number;
18
+ readonly layout: PanelLayout | undefined;
19
+ readonly close: () => void;
20
+ /** Gets focus back after Escape. */
21
+ readonly returnFocus: HTMLElement;
22
+ }
23
+
24
+ /** Show a panel beside its anchor, and close it the usual ways. Returns the way to undo that. */
25
+ export function openPanel(options: OpenPanel): () => void {
26
+ const { panel, close } = options;
27
+ panel.hidden = false;
28
+ const stopTracking = trackPosition(options.anchor, panel, {
29
+ width: options.width,
30
+ layout: options.layout,
31
+ });
32
+ const stopOutside = onOutsidePointer(options.inside, close);
33
+ const stopBackdrop = onBackdropPointer(panel, close);
34
+ const stopEscape = onEscape(() => {
35
+ close();
36
+ restoreFocus(options.returnFocus);
37
+ });
38
+
39
+ return () => {
40
+ stopTracking();
41
+ stopOutside();
42
+ stopBackdrop();
43
+ stopEscape();
44
+ panel.hidden = true;
45
+ };
46
+ }
47
+
48
+ /** The BS/AD buttons in a panel's footer. */
49
+ export function renderSegment(
50
+ segment: HTMLElement,
51
+ state: { readonly canSwitchCalendar: boolean; readonly calendar: CalendarSystem },
52
+ locale: LocaleData,
53
+ ): void {
54
+ segment.hidden = !state.canSwitchCalendar;
55
+ setAttrs(segment, { 'aria-label': locale.labels.calendar });
56
+ for (const button of segment.querySelectorAll<HTMLButtonElement>('button')) {
57
+ const calendar = button.dataset['calendar'] === 'AD' ? 'AD' : 'BS';
58
+ setText(button, locale.calendarNames[calendar]);
59
+ setAttrs(button, { 'aria-pressed': String(calendar === state.calendar) });
60
+ }
61
+ }
@@ -6,15 +6,9 @@ import {
6
6
  type DatePickerState,
7
7
  type DatePickerStore,
8
8
  } from '@nepdatejs/datepicker';
9
- import {
10
- onBackdropPointer,
11
- onEscape,
12
- onOutsidePointer,
13
- restoreFocus,
14
- trackPosition,
15
- type PanelLayout,
16
- } from '@nepdatejs/dom';
9
+ import { restoreFocus, type PanelLayout } from '@nepdatejs/dom';
17
10
  import { CalendarView } from './calendar-view';
11
+ import { openPanel, renderSegment } from './panel';
18
12
  import { el, icon, setAttrs, setPopupMode, setText, uid } from './dom';
19
13
  import { PANEL_WIDTH, PANEL_WIDTH_WITH_PRESETS, PresetList } from './preset-list';
20
14
 
@@ -282,15 +276,7 @@ export class DatePickerView {
282
276
  setText(this.hint, hintText ?? '');
283
277
  setAttrs(this.hint, { 'data-error': state.error !== null });
284
278
 
285
- this.segment.hidden = !state.canSwitchCalendar;
286
- setAttrs(this.segment, { 'aria-label': locale.labels.calendar });
287
- for (const button of this.segment.querySelectorAll<HTMLButtonElement>('button')) {
288
- const calendar = button.dataset['calendar'] as CalendarSystem;
289
- setText(button, locale.calendarNames[calendar]);
290
- setAttrs(button, {
291
- 'aria-pressed': calendar === state.calendar ? 'true' : 'false',
292
- });
293
- }
279
+ renderSegment(this.segment, state, locale);
294
280
  setText(this.todayButton, locale.labels.today);
295
281
  this.presetList.render(state.presets, locale.labels.presets);
296
282
 
@@ -321,28 +307,17 @@ export class DatePickerView {
321
307
  this.wasOpen = open;
322
308
  this.options.onOpenChange?.(open);
323
309
  if (open) {
324
- this.panel.hidden = false;
325
- const stopTracking = trackPosition(this.box, this.panel, {
310
+ this.closePanel = openPanel({
311
+ panel: this.panel,
312
+ anchor: this.box,
313
+ inside: [this.field, this.panel],
326
314
  width: this.panelWidth(),
327
315
  layout: this.options.panelLayout,
316
+ close: () => {
317
+ this.store.actions.close();
318
+ },
319
+ returnFocus: this.input,
328
320
  });
329
- const stopOutside = onOutsidePointer([this.field, this.panel], () => {
330
- this.store.actions.close();
331
- });
332
- const stopBackdrop = onBackdropPointer(this.panel, () => {
333
- this.store.actions.close();
334
- });
335
- const stopEscape = onEscape(() => {
336
- this.store.actions.close();
337
- restoreFocus(this.input);
338
- });
339
- this.closePanel = () => {
340
- stopTracking();
341
- stopOutside();
342
- stopBackdrop();
343
- stopEscape();
344
- this.panel.hidden = true;
345
- };
346
321
  this.calendarView.focusGrid();
347
322
  } else {
348
323
  this.closePanel?.();
package/src/range-view.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { getLocale, type CalendarSystem } from '@nepdatejs/core';
1
+ import { getLocale } from '@nepdatejs/core';
2
2
  import {
3
3
  createDateRangePicker,
4
4
  type DateRangePickerOptions,
@@ -6,15 +6,9 @@ import {
6
6
  type DateRangePickerStore,
7
7
  type RangeField,
8
8
  } from '@nepdatejs/datepicker';
9
- import {
10
- onBackdropPointer,
11
- onEscape,
12
- onOutsidePointer,
13
- restoreFocus,
14
- trackPosition,
15
- type PanelLayout,
16
- } from '@nepdatejs/dom';
9
+ import { restoreFocus, type PanelLayout } from '@nepdatejs/dom';
17
10
  import { CalendarView } from './calendar-view';
11
+ import { openPanel, renderSegment } from './panel';
18
12
  import { el, icon, setAttrs, setPopupMode, setText, uid } from './dom';
19
13
  import { PANEL_WIDTH, PANEL_WIDTH_WITH_PRESETS, PresetList } from './preset-list';
20
14
  import type { Theme } from './picker-view';
@@ -279,15 +273,7 @@ export class DateRangePickerView {
279
273
  this.hint.hidden = hintText === null;
280
274
  setText(this.hint, hintText ?? '');
281
275
  setAttrs(this.hint, { 'data-error': hintText !== null });
282
- this.segment.hidden = !state.canSwitchCalendar;
283
- setAttrs(this.segment, { 'aria-label': locale.labels.calendar });
284
- for (const button of this.segment.querySelectorAll<HTMLButtonElement>('button')) {
285
- const calendar = button.dataset['calendar'] as CalendarSystem;
286
- setText(button, locale.calendarNames[calendar]);
287
- setAttrs(button, {
288
- 'aria-pressed': calendar === state.calendar ? 'true' : 'false',
289
- });
290
- }
276
+ renderSegment(this.segment, state, locale);
291
277
  this.presetList.render(state.presets, locale.labels.presets);
292
278
  const fiscal = this.options.fiscalYearView ?? false;
293
279
  this.fiscalButton.hidden = !fiscal;
@@ -323,29 +309,18 @@ export class DateRangePickerView {
323
309
  this.wasOpen = open;
324
310
  this.options.onOpenChange?.(open);
325
311
  if (open) {
326
- this.panel.hidden = false;
327
312
  const anchor = this.field.querySelector('.ndp-range') ?? this.field;
328
- const stopTracking = trackPosition(anchor, this.panel, {
313
+ this.closePanel = openPanel({
314
+ panel: this.panel,
315
+ anchor,
316
+ inside: [this.field],
329
317
  width: this.panelWidth(),
330
318
  layout: this.options.panelLayout,
319
+ close: () => {
320
+ this.store.actions.close();
321
+ },
322
+ returnFocus: this.inputs.start,
331
323
  });
332
- const stopOutside = onOutsidePointer([this.field], () => {
333
- this.store.actions.close();
334
- });
335
- const stopBackdrop = onBackdropPointer(this.panel, () => {
336
- this.store.actions.close();
337
- });
338
- const stopEscape = onEscape(() => {
339
- this.store.actions.close();
340
- restoreFocus(this.inputs.start);
341
- });
342
- this.closePanel = () => {
343
- stopTracking();
344
- stopOutside();
345
- stopBackdrop();
346
- stopEscape();
347
- this.panel.hidden = true;
348
- };
349
324
  this.calendarView.focusGrid();
350
325
  } else {
351
326
  this.closePanel?.();