@newthink/ui 0.1.3 → 0.2.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.
@@ -0,0 +1,6 @@
1
+ import { HeadlessComponent } from './headless';
2
+ export declare const accordionGroup: HeadlessComponent;
3
+ export declare const accordion: HeadlessComponent;
4
+ declare const accordions: HeadlessComponent;
5
+ export default accordions;
6
+ //# sourceMappingURL=accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../src/headless/accordion.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EAIlB,MAAM,YAAY,CAAC;AAgDpB,eAAO,MAAM,cAAc,EAAE,iBAC8B,CAAC;AAqD5D,eAAO,MAAM,SAAS,mBAIrB,CAAC;AAEF,QAAA,MAAM,UAAU,EAAE,iBAGjB,CAAC;AACF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { headless, } from './headless';
2
+ const groupMap = new WeakMap();
3
+ const getGroup = (el, Alpine) => {
4
+ const root = Alpine.findClosest(el, groupMap.has.bind(groupMap));
5
+ return groupMap.get(root);
6
+ };
7
+ const handleAccordionGroup = (el, _, { Alpine, effect }) => {
8
+ const groupData = Alpine.reactive({
9
+ active: null,
10
+ id: 0,
11
+ addAccordion(initial) {
12
+ const thisId = this.id++;
13
+ const accordionInstance = Alpine.reactive({
14
+ active: initial,
15
+ });
16
+ effect(() => {
17
+ if (accordionInstance.active) {
18
+ this.active = thisId;
19
+ }
20
+ else if (this.active === thisId) {
21
+ this.active = null;
22
+ }
23
+ });
24
+ effect(() => {
25
+ if (this.active === thisId) {
26
+ accordionInstance.active = true;
27
+ }
28
+ else {
29
+ accordionInstance.active = false;
30
+ }
31
+ });
32
+ return accordionInstance;
33
+ },
34
+ });
35
+ groupMap.set(el, groupData);
36
+ return groupData;
37
+ };
38
+ export const accordionGroup = (Alpine) => Alpine.directive('accordion-group', handleAccordionGroup);
39
+ const handleAccordionRoot = (el, { modifiers: [initialState = 'closed'] }, { Alpine }) => getGroup(el, Alpine)?.addAccordion(initialState === 'open') ??
40
+ Alpine.reactive({
41
+ active: initialState === 'open',
42
+ });
43
+ const controlForce = {
44
+ open: true,
45
+ close: false,
46
+ toggle: null,
47
+ };
48
+ const handleAccordionControl = (accordionData, el, { modifiers: [force = 'toggle'] }, { Alpine }) => {
49
+ Alpine.bind(el, {
50
+ 'x-on:click': () => {
51
+ accordionData.active =
52
+ controlForce[force] ?? !accordionData.active;
53
+ },
54
+ ':aria-expanded': () => accordionData.active,
55
+ });
56
+ };
57
+ const handleAccordionContainer = (accordionData, el, _, { Alpine }) => {
58
+ Alpine.bind(el, {
59
+ 'x-show': () => accordionData.active,
60
+ });
61
+ };
62
+ const accordionHandlers = {
63
+ control: handleAccordionControl,
64
+ container: handleAccordionContainer,
65
+ };
66
+ export const accordion = headless('accordion', handleAccordionRoot, accordionHandlers);
67
+ const accordions = (Alpine) => {
68
+ accordionGroup(Alpine);
69
+ accordion(Alpine);
70
+ };
71
+ export default accordions;
72
+ //# sourceMappingURL=accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../src/headless/accordion.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAIxD,eAAO,MAAM,EAAE,EAAE,iBAA4D,CAAC;AAE9E,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAIxD,eAAO,MAAM,EAAE,EAAE,iBACyB,CAAC;AAE3C,eAAe,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
+ import accordions from './headless/accordion';
1
2
  import { panel } from './headless/panel';
2
3
  import { tabs } from './headless/tabs';
3
- export const UI = (Alpine) => Alpine.plugin([panel, tabs]);
4
+ export const UI = (Alpine) => Alpine.plugin([accordions, panel, tabs]);
4
5
  export default UI;
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,CAAC,MAAM,EAAE,GAAsB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAE9E,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,CAAC,MAAM,EAAE,GAAsB,CAAC,MAAM,EAAE,EAAE,CAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAE3C,eAAe,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newthink/ui",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Simple Alpine Headless UI Components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -22,14 +22,14 @@
22
22
  "license": "ISC",
23
23
  "devDependencies": {
24
24
  "@trivago/prettier-plugin-sort-imports": "4.1.1",
25
- "@types/node": "20.2.5",
26
- "@typescript-eslint/eslint-plugin": "5.59.9",
27
- "@typescript-eslint/parser": "5.59.9",
28
- "@vitest/coverage-c8": "0.32.0",
25
+ "@types/node": "20.3.1",
26
+ "@typescript-eslint/eslint-plugin": "5.59.11",
27
+ "@typescript-eslint/parser": "5.59.11",
28
+ "@vitest/coverage-c8": "0.32.1",
29
29
  "alpinejs": "npm:@ekwoka/alpinets@0.0.1-alpha",
30
- "esbuild": "0.17.19",
30
+ "esbuild": "0.18.3",
31
31
  "eslint": "8.42.0",
32
- "eslint-plugin-filename-export": "1.0.3",
32
+ "eslint-plugin-filename-export": "1.0.4",
33
33
  "husky": "8.0.3",
34
34
  "lint-staged": "13.2.2",
35
35
  "prettier": "2.8.8",
@@ -37,7 +37,7 @@
37
37
  "typescript": "5.1.3",
38
38
  "vite": "4.3.9",
39
39
  "vite-tsconfig-paths": "4.2.0",
40
- "vitest": "0.32.0"
40
+ "vitest": "0.32.1"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "alpinejs": "^3.10.0",
@@ -0,0 +1,120 @@
1
+ import { Alpine } from 'alpinejs';
2
+
3
+ import {
4
+ HeadlessComponent,
5
+ HeadlessHandler,
6
+ RootHandler,
7
+ headless,
8
+ } from './headless';
9
+
10
+ type GroupData = {
11
+ active: number | null;
12
+ id: number;
13
+ addAccordion: (initial: boolean) => AccordionData;
14
+ };
15
+ const groupMap = new WeakMap<HTMLElement, GroupData>();
16
+
17
+ const getGroup = (el: HTMLElement, Alpine: Alpine) => {
18
+ const root = Alpine.findClosest(el, groupMap.has.bind(groupMap));
19
+ return groupMap.get(root);
20
+ };
21
+
22
+ const handleAccordionGroup: RootHandler<GroupData> = (
23
+ el,
24
+ _,
25
+ { Alpine, effect }
26
+ ) => {
27
+ const groupData = Alpine.reactive({
28
+ active: null as number | null,
29
+ id: 0,
30
+ addAccordion(initial: boolean) {
31
+ const thisId = this.id++;
32
+ const accordionInstance = Alpine.reactive({
33
+ active: initial,
34
+ });
35
+ effect(() => {
36
+ if (accordionInstance.active) {
37
+ this.active = thisId;
38
+ } else if (this.active === thisId) {
39
+ this.active = null;
40
+ }
41
+ });
42
+ effect(() => {
43
+ if (this.active === thisId) {
44
+ accordionInstance.active = true;
45
+ } else {
46
+ accordionInstance.active = false;
47
+ }
48
+ });
49
+ return accordionInstance;
50
+ },
51
+ });
52
+ groupMap.set(el, groupData);
53
+ return groupData;
54
+ };
55
+
56
+ export const accordionGroup: HeadlessComponent = (Alpine) =>
57
+ Alpine.directive('accordion-group', handleAccordionGroup);
58
+
59
+ type AccordionData = {
60
+ active: boolean;
61
+ };
62
+ const handleAccordionRoot: RootHandler<AccordionData> = (
63
+ el,
64
+ { modifiers: [initialState = 'closed'] },
65
+ { Alpine }
66
+ ) =>
67
+ getGroup(el, Alpine)?.addAccordion(initialState === 'open') ??
68
+ Alpine.reactive({
69
+ active: initialState === 'open',
70
+ });
71
+
72
+ const controlForce = {
73
+ open: true,
74
+ close: false,
75
+ toggle: null,
76
+ };
77
+
78
+ type controlType = keyof typeof controlForce;
79
+
80
+ const handleAccordionControl: HeadlessHandler<AccordionData> = (
81
+ accordionData,
82
+ el,
83
+ { modifiers: [force = 'toggle'] },
84
+ { Alpine }
85
+ ) => {
86
+ Alpine.bind(el, {
87
+ 'x-on:click': () => {
88
+ accordionData.active =
89
+ controlForce[force as controlType] ?? !accordionData.active;
90
+ },
91
+ ':aria-expanded': () => accordionData.active,
92
+ });
93
+ };
94
+ const handleAccordionContainer: HeadlessHandler<AccordionData> = (
95
+ accordionData,
96
+ el,
97
+ _,
98
+ { Alpine }
99
+ ) => {
100
+ Alpine.bind(el, {
101
+ 'x-show': () => accordionData.active,
102
+ });
103
+ };
104
+
105
+ const accordionHandlers = {
106
+ control: handleAccordionControl,
107
+ container: handleAccordionContainer,
108
+ };
109
+
110
+ export const accordion = headless(
111
+ 'accordion',
112
+ handleAccordionRoot,
113
+ accordionHandlers
114
+ );
115
+
116
+ const accordions: HeadlessComponent = (Alpine) => {
117
+ accordionGroup(Alpine);
118
+ accordion(Alpine);
119
+ };
120
+ export default accordions;
package/src/index.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import accordions from './headless/accordion';
1
2
  import { HeadlessComponent } from './headless/headless';
2
3
  import { panel } from './headless/panel';
3
4
  import { tabs } from './headless/tabs';
4
5
 
5
- export const UI: HeadlessComponent = (Alpine) => Alpine.plugin([panel, tabs]);
6
+ export const UI: HeadlessComponent = (Alpine) =>
7
+ Alpine.plugin([accordions, panel, tabs]);
6
8
 
7
9
  export default UI;