@syntrologie/adapt-faq 0.0.0-semantically-released → 2.0.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.
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Adaptive FAQ - Action Executors
3
+ *
4
+ * Three executors that operate on the FAQStore:
5
+ * - executeScrollToFaq: scroll to a FAQ item and optionally expand it
6
+ * - executeToggleFaqItem: open / close / toggle a FAQ item
7
+ * - executeUpdateFaq: add, remove, reorder, or replace FAQ items
8
+ */
9
+ import type { FAQStore } from './state';
10
+ import type { ScrollToFaqAction, ToggleFaqItemAction, UpdateFaqAction, ExecutorResult, ExecutorContext } from './types';
11
+ /**
12
+ * Scroll to a FAQ item in the DOM and optionally expand it.
13
+ *
14
+ * Looks up the item by `itemId` or `itemQuestion`, scrolls the matching
15
+ * `[data-faq-item-id]` element into view, and expands it unless
16
+ * `expand` is explicitly set to `false`.
17
+ */
18
+ export declare function executeScrollToFaq(action: ScrollToFaqAction, context: ExecutorContext, store: FAQStore): Promise<ExecutorResult>;
19
+ /**
20
+ * Open, close, or toggle a FAQ item's expanded state.
21
+ */
22
+ export declare function executeToggleFaqItem(action: ToggleFaqItemAction, context: ExecutorContext, store: FAQStore): Promise<ExecutorResult>;
23
+ /**
24
+ * Add, remove, reorder, or replace FAQ items in the store.
25
+ */
26
+ export declare function executeUpdateFaq(action: UpdateFaqAction, context: ExecutorContext, store: FAQStore): Promise<ExecutorResult>;
27
+ /**
28
+ * All executors provided by adaptive-faq.
29
+ * These are registered with the runtime's ExecutorRegistry.
30
+ */
31
+ export declare const executorDefinitions: readonly [{
32
+ readonly kind: "faq:scroll_to";
33
+ readonly executor: typeof executeScrollToFaq;
34
+ }, {
35
+ readonly kind: "faq:toggle_item";
36
+ readonly executor: typeof executeToggleFaqItem;
37
+ }, {
38
+ readonly kind: "faq:update";
39
+ readonly executor: typeof executeUpdateFaq;
40
+ }];
41
+ //# sourceMappingURL=executors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executors.d.ts","sourceRoot":"","sources":["../src/executors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,eAAe,EAEhB,MAAM,SAAS,CAAC;AA4BjB;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAMD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CAgCzB;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CA0CzB;AAMD;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;EAItB,CAAC"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Adaptive FAQ - Action Executors
3
+ *
4
+ * Three executors that operate on the FAQStore:
5
+ * - executeScrollToFaq: scroll to a FAQ item and optionally expand it
6
+ * - executeToggleFaqItem: open / close / toggle a FAQ item
7
+ * - executeUpdateFaq: add, remove, reorder, or replace FAQ items
8
+ */
9
+ // ============================================================================
10
+ // Helpers
11
+ // ============================================================================
12
+ /**
13
+ * Resolve a FAQ item by direct ID or by fuzzy question text match.
14
+ * Throws if neither yields a result.
15
+ */
16
+ function resolveItem(store, itemId, itemQuestion) {
17
+ if (itemId) {
18
+ const found = store.getState().items.find((i) => i.config.id === itemId);
19
+ if (found)
20
+ return found;
21
+ }
22
+ if (itemQuestion) {
23
+ const found = store.findByQuestion(itemQuestion);
24
+ if (found)
25
+ return found;
26
+ }
27
+ throw new Error('FAQ item not found');
28
+ }
29
+ // ============================================================================
30
+ // executeScrollToFaq
31
+ // ============================================================================
32
+ /**
33
+ * Scroll to a FAQ item in the DOM and optionally expand it.
34
+ *
35
+ * Looks up the item by `itemId` or `itemQuestion`, scrolls the matching
36
+ * `[data-faq-item-id]` element into view, and expands it unless
37
+ * `expand` is explicitly set to `false`.
38
+ */
39
+ export async function executeScrollToFaq(action, context, store) {
40
+ const item = resolveItem(store, action.itemId, action.itemQuestion);
41
+ const { id } = item.config;
42
+ // Expand the item unless explicitly told not to
43
+ if (action.expand !== false) {
44
+ store.expand(id);
45
+ }
46
+ // Scroll the DOM element into view (may be absent in test environments)
47
+ const el = document.querySelector(`[data-faq-item-id="${id}"]`);
48
+ if (el) {
49
+ el.scrollIntoView({
50
+ behavior: action.behavior ?? 'smooth',
51
+ });
52
+ }
53
+ // Publish analytics event
54
+ context.publishEvent('faq:scroll_to', { itemId: id });
55
+ return {
56
+ cleanup: () => {
57
+ // Optionally collapse on revert
58
+ },
59
+ };
60
+ }
61
+ // ============================================================================
62
+ // executeToggleFaqItem
63
+ // ============================================================================
64
+ /**
65
+ * Open, close, or toggle a FAQ item's expanded state.
66
+ */
67
+ export async function executeToggleFaqItem(action, context, store) {
68
+ const item = resolveItem(store, action.itemId, action.itemQuestion);
69
+ const { id } = item.config;
70
+ const desiredState = action.state ?? 'toggle';
71
+ let newState;
72
+ switch (desiredState) {
73
+ case 'open':
74
+ store.expand(id);
75
+ newState = 'open';
76
+ break;
77
+ case 'closed':
78
+ store.collapse(id);
79
+ newState = 'closed';
80
+ break;
81
+ case 'toggle':
82
+ default: {
83
+ const wasExpanded = store.getState().expandedItems.has(id);
84
+ store.toggle(id);
85
+ newState = wasExpanded ? 'closed' : 'open';
86
+ break;
87
+ }
88
+ }
89
+ context.publishEvent('faq:toggle', { itemId: id, newState });
90
+ return {
91
+ cleanup: () => {
92
+ // Revert toggle on cleanup
93
+ },
94
+ };
95
+ }
96
+ // ============================================================================
97
+ // executeUpdateFaq
98
+ // ============================================================================
99
+ /**
100
+ * Add, remove, reorder, or replace FAQ items in the store.
101
+ */
102
+ export async function executeUpdateFaq(action, context, store) {
103
+ switch (action.operation) {
104
+ case 'add': {
105
+ const items = action.items ?? [];
106
+ const position = action.position === 'prepend' ? 'prepend' : 'append';
107
+ store.addItems(items, position);
108
+ break;
109
+ }
110
+ case 'remove': {
111
+ if (!action.itemId) {
112
+ throw new Error('FAQ item not found');
113
+ }
114
+ // Verify the item exists before removing
115
+ const exists = store.getState().items.some((i) => i.config.id === action.itemId);
116
+ if (!exists) {
117
+ throw new Error('FAQ item not found');
118
+ }
119
+ store.removeItem(action.itemId);
120
+ break;
121
+ }
122
+ case 'reorder': {
123
+ const order = action.order ?? [];
124
+ store.reorderItems(order);
125
+ break;
126
+ }
127
+ case 'replace': {
128
+ const items = action.items ?? [];
129
+ store.replaceItems(items);
130
+ break;
131
+ }
132
+ }
133
+ context.publishEvent('faq:update', { operation: action.operation });
134
+ return {
135
+ cleanup: () => {
136
+ // Could snapshot previous state for undo
137
+ },
138
+ };
139
+ }
140
+ // ============================================================================
141
+ // Executor Definitions for Registration
142
+ // ============================================================================
143
+ /**
144
+ * All executors provided by adaptive-faq.
145
+ * These are registered with the runtime's ExecutorRegistry.
146
+ */
147
+ export const executorDefinitions = [
148
+ { kind: 'faq:scroll_to', executor: executeScrollToFaq },
149
+ { kind: 'faq:toggle_item', executor: executeToggleFaqItem },
150
+ { kind: 'faq:update', executor: executeUpdateFaq },
151
+ ];
package/dist/runtime.d.ts CHANGED
@@ -2,14 +2,14 @@
2
2
  * Adaptive FAQ - Runtime Module
3
3
  *
4
4
  * Runtime manifest for the FAQ accordion adaptive.
5
- * This is a widget-based adaptive with no action executors.
5
+ * Provides action executors and widget registration.
6
6
  */
7
7
  /**
8
8
  * Runtime manifest for adaptive-faq.
9
9
  *
10
- * Note: This adaptive is widget-based, not action-based.
11
- * The `faq:question` actions are compositional - they're rendered by
12
- * the widget, not executed by the runtime.
10
+ * Provides:
11
+ * - FAQ action executors (scroll_to, toggle_item, update)
12
+ * - Widget-based accordion (compositional faq:question actions)
13
13
  */
14
14
  export declare const runtime: {
15
15
  id: string;
@@ -17,10 +17,18 @@ export declare const runtime: {
17
17
  name: string;
18
18
  description: string;
19
19
  /**
20
- * No action executors - faq:question actions are compositional,
21
- * meaning they serve as configuration for the FAQWidget.
20
+ * Action executors for programmatic FAQ interaction.
22
21
  */
23
- executors: never[];
22
+ executors: readonly [{
23
+ readonly kind: "faq:scroll_to";
24
+ readonly executor: typeof import("./executors").executeScrollToFaq;
25
+ }, {
26
+ readonly kind: "faq:toggle_item";
27
+ readonly executor: typeof import("./executors").executeToggleFaqItem;
28
+ }, {
29
+ readonly kind: "faq:update";
30
+ readonly executor: typeof import("./executors").executeUpdateFaq;
31
+ }];
24
32
  /**
25
33
  * Widget definitions for the runtime's WidgetRegistry.
26
34
  */
@@ -28,7 +36,7 @@ export declare const runtime: {
28
36
  id: string;
29
37
  component: {
30
38
  mount(container: HTMLElement, config?: import("./types").FAQConfig & {
31
- runtime?: import("./types").FAQWidgetRuntime;
39
+ runtime?: import("./FAQWidget").FAQWidgetRuntime;
32
40
  instanceId?: string;
33
41
  }): () => void;
34
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;;;;;GAMG;AACH,eAAO,MAAM,OAAO;;;;;IAMlB;;;OAGG;;IAGH;;OAEG;;;;;uBAey/S,CAAC;0BAA8B,CAAC;;;;;;;;;CAH7hT,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;;;;GAMG;AACH,eAAO,MAAM,OAAO;;;;;IAOlB;;OAEG;;;;;;;;;;;IAGH;;OAEG;;;;;uBAeu2f,CAAC;0BAA8B,CAAC;;;;;;;;;CAH34f,CAAC;AAEF,eAAe,OAAO,CAAC"}
package/dist/runtime.js CHANGED
@@ -2,8 +2,9 @@
2
2
  * Adaptive FAQ - Runtime Module
3
3
  *
4
4
  * Runtime manifest for the FAQ accordion adaptive.
5
- * This is a widget-based adaptive with no action executors.
5
+ * Provides action executors and widget registration.
6
6
  */
7
+ import { executorDefinitions } from './executors';
7
8
  import { FAQMountableWidget } from './FAQWidget';
8
9
  // ============================================================================
9
10
  // App Runtime Manifest
@@ -11,20 +12,19 @@ import { FAQMountableWidget } from './FAQWidget';
11
12
  /**
12
13
  * Runtime manifest for adaptive-faq.
13
14
  *
14
- * Note: This adaptive is widget-based, not action-based.
15
- * The `faq:question` actions are compositional - they're rendered by
16
- * the widget, not executed by the runtime.
15
+ * Provides:
16
+ * - FAQ action executors (scroll_to, toggle_item, update)
17
+ * - Widget-based accordion (compositional faq:question actions)
17
18
  */
18
19
  export const runtime = {
19
20
  id: 'adaptive-faq',
20
- version: '1.0.0',
21
+ version: '2.0.0',
21
22
  name: 'FAQ Accordion',
22
- description: 'Collapsible Q&A accordion with per-item conditional visibility',
23
+ description: 'Collapsible Q&A accordion with actions, rich content, feedback, and personalization',
23
24
  /**
24
- * No action executors - faq:question actions are compositional,
25
- * meaning they serve as configuration for the FAQWidget.
25
+ * Action executors for programmatic FAQ interaction.
26
26
  */
27
- executors: [],
27
+ executors: executorDefinitions,
28
28
  /**
29
29
  * Widget definitions for the runtime's WidgetRegistry.
30
30
  */
@@ -34,7 +34,7 @@ export const runtime = {
34
34
  component: FAQMountableWidget,
35
35
  metadata: {
36
36
  name: 'FAQ Accordion',
37
- description: 'Collapsible Q&A accordion with search',
37
+ description: 'Collapsible Q&A accordion with search, categories, and feedback',
38
38
  icon: '❓',
39
39
  },
40
40
  },