@rettangoli/ui 0.1.2-rc3 → 0.1.2-rc30

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 (54) hide show
  1. package/dist/rettangoli-iife-layout.min.js +115 -43
  2. package/dist/rettangoli-iife-ui.min.js +187 -67
  3. package/package.json +5 -3
  4. package/src/cli/buildSvg.js +86 -0
  5. package/src/cli/index.js +1 -0
  6. package/src/common.js +19 -0
  7. package/src/components/breadcrumb/breadcrumb.handlers.js +9 -0
  8. package/src/components/breadcrumb/breadcrumb.store.js +29 -0
  9. package/src/components/breadcrumb/breadcrumb.view.yaml +64 -0
  10. package/src/components/dropdownMenu/dropdownMenu.handlers.js +4 -4
  11. package/src/components/dropdownMenu/dropdownMenu.store.js +5 -17
  12. package/src/components/dropdownMenu/dropdownMenu.view.yaml +15 -13
  13. package/src/components/form/form.handlers.js +173 -25
  14. package/src/components/form/form.store.js +176 -22
  15. package/src/components/form/form.view.yaml +217 -33
  16. package/src/components/pageOutline/pageOutline.handlers.js +1 -1
  17. package/src/components/popoverInput/popoverInput.handlers.js +99 -0
  18. package/src/components/popoverInput/popoverInput.store.js +48 -0
  19. package/src/components/popoverInput/popoverInput.view.yaml +55 -0
  20. package/src/components/select/select.handlers.js +116 -11
  21. package/src/components/select/select.store.js +84 -18
  22. package/src/components/select/select.view.yaml +40 -10
  23. package/src/components/sidebar/sidebar.view.yaml +1 -1
  24. package/src/components/sliderInput/sliderInput.handlers.js +41 -0
  25. package/src/components/sliderInput/sliderInput.store.js +18 -0
  26. package/src/components/sliderInput/sliderInput.view.yaml +42 -0
  27. package/src/components/table/table.handlers.js +1 -1
  28. package/src/components/tabs/tabs.handlers.js +10 -0
  29. package/src/components/tabs/tabs.store.js +29 -0
  30. package/src/components/tabs/tabs.view.yaml +64 -0
  31. package/src/components/tooltip/tooltip.handlers.js +0 -0
  32. package/src/components/tooltip/tooltip.store.js +12 -0
  33. package/src/components/tooltip/tooltip.view.yaml +27 -0
  34. package/src/components/waveform/waveform.handlers.js +92 -0
  35. package/src/components/waveform/waveform.store.js +17 -0
  36. package/src/components/waveform/waveform.view.yaml +38 -0
  37. package/src/entry-iife-layout.js +3 -0
  38. package/src/entry-iife-ui.js +4 -0
  39. package/src/index.js +5 -1
  40. package/src/primitives/button.js +10 -0
  41. package/src/primitives/colorPicker.js +9 -0
  42. package/src/primitives/dialog.js +254 -0
  43. package/src/primitives/input.js +41 -11
  44. package/src/primitives/popover.js +280 -0
  45. package/src/primitives/slider.js +18 -9
  46. package/src/primitives/svg.js +2 -0
  47. package/src/primitives/textarea.js +25 -1
  48. package/src/styles/cursorStyles.js +38 -2
  49. package/src/components/dialog/dialog.handlers.js +0 -5
  50. package/src/components/dialog/dialog.store.js +0 -25
  51. package/src/components/dialog/dialog.view.yaml +0 -44
  52. package/src/components/popover/popover.handlers.js +0 -5
  53. package/src/components/popover/popover.store.js +0 -12
  54. package/src/components/popover/popover.view.yaml +0 -57
@@ -1,45 +1,199 @@
1
+ import { parseAndRender } from "jempl";
2
+
3
+ const encode = (input) => {
4
+ function escapeHtml(text) {
5
+ const map = {
6
+ '&': '&',
7
+ '<': '&lt;',
8
+ '>': '&gt;',
9
+ '"': '&quot;',
10
+ "'": '&#39;'
11
+ };
12
+ return text.replace(/[&<>"']/g, char => map[char]);
13
+ }
14
+ if (input === undefined || input === null) {
15
+ return ""
16
+ }
17
+ return `"${escapeHtml(String(input))}"`;
18
+ }
19
+
20
+ function pick(obj, keys) {
21
+ return keys.reduce((acc, key) => {
22
+ if (key in obj) acc[key] = obj[key];
23
+ return acc;
24
+ }, {});
25
+ }
26
+
1
27
  export const INITIAL_STATE = Object.freeze({
2
- formValues: {}
28
+ formValues: {},
29
+ tooltipState: {
30
+ open: false,
31
+ x: 0,
32
+ y: 0,
33
+ content: ''
34
+ },
3
35
  });
4
36
 
5
- const blacklistedAttrs = ['id', 'class', 'style', 'slot'];
37
+ // Lodash-like utility functions for nested property access
38
+ const get = (obj, path, defaultValue = undefined) => {
39
+ if (!path) {
40
+ return;
41
+ }
42
+ const keys = path.split(/[\[\].]/).filter((key) => key !== "");
43
+ let current = obj;
44
+
45
+ for (const key of keys) {
46
+ if (current === null || current === undefined || !(key in current)) {
47
+ return defaultValue;
48
+ }
49
+ current = current[key];
50
+ }
51
+ return current;
52
+ };
53
+
54
+ const set = (obj, path, value) => {
55
+ const keys = path.split(/[\[\].]/).filter((key) => key !== "");
56
+
57
+ // If path contains array notation, delete the original flat key
58
+ if (path.includes("[") && path in obj) {
59
+ delete obj[path];
60
+ }
61
+
62
+ let current = obj;
63
+
64
+ for (let i = 0; i < keys.length - 1; i++) {
65
+ const key = keys[i];
66
+ if (
67
+ !(key in current) ||
68
+ typeof current[key] !== "object" ||
69
+ current[key] === null
70
+ ) {
71
+ // Check if next key is a number to create array
72
+ const nextKey = keys[i + 1];
73
+ const isArrayIndex = /^\d+$/.test(nextKey);
74
+ current[key] = isArrayIndex ? [] : {};
75
+ }
76
+ current = current[key];
77
+ }
78
+
79
+ current[keys[keys.length - 1]] = value;
80
+ return obj;
81
+ };
82
+
83
+ const blacklistedAttrs = ["id", "class", "style", "slot"];
6
84
 
7
85
  const stringifyAttrs = (attrs) => {
8
- return Object.entries(attrs).filter(([key]) => !blacklistedAttrs.includes(key)).map(([key, value]) => `${key}=${value}`).join(' ');
9
- }
86
+ return Object.entries(attrs)
87
+ .filter(([key]) => !blacklistedAttrs.includes(key))
88
+ .map(([key, value]) => `${key}=${value}`)
89
+ .join(" ");
90
+ };
91
+
92
+ export const selectForm = ({ state, props }) => {
93
+ const { form } = props;
94
+ const { context } = props;
95
+
96
+ if (context) {
97
+ return parseAndRender(form, context);
98
+ }
99
+
100
+ return form;
101
+ };
102
+
10
103
 
11
104
  export const toViewData = ({ state, props, attrs }) => {
12
105
  const containerAttrString = stringifyAttrs(attrs);
106
+ const defaultValues = props.defaultValues || {};
107
+
108
+ const form = selectForm({ state, props });
109
+ const fields = structuredClone(form.fields || []);
110
+ fields.forEach((field) => {
111
+ // Use formValues from state if available, otherwise fall back to defaultValues from props
112
+ const defaultValue = get(state.formValues, field.name) ?? get(defaultValues, field.name)
113
+ if (["popover-input", "select", "read-only-text"].includes(field.inputType)) {
114
+ field.defaultValue = defaultValue
115
+ } else {
116
+ field.defaultValue = encode(defaultValue);
117
+ }
118
+
119
+ if (["inputText"].includes(field.inputType)) {
120
+ field.placeholder = encode(field.placeholder)
121
+ }
122
+
123
+ if (field.inputType === "image") {
124
+ const src = field.src;
125
+ // Only set imageSrc if src exists and is not empty
126
+ field.imageSrc = src && src.trim() ? src : null;
127
+ // Set placeholder text
128
+ field.placeholderText = field.placeholder || "No Image";
129
+ }
130
+ if (field.inputType === "waveform") {
131
+ const waveformData = field.waveformData;
132
+ // Only set waveformData if it exists
133
+ field.waveformData = waveformData || null;
134
+ // Set placeholder text
135
+ field.placeholderText = field.placeholder || "No Waveform";
136
+ }
137
+ });
138
+
13
139
  return {
140
+ key: attrs?.key,
14
141
  containerAttrString,
15
- title: props.form?.title || '',
16
- description: props?.form?.description || '',
17
- fields: props?.form?.fields || [],
142
+ title: form?.title || "",
143
+ description: form?.description || "",
144
+ fields: fields,
18
145
  actions: props?.form?.actions || {
19
- buttons: []
146
+ buttons: [],
20
147
  },
21
- // TODO fix default values
22
148
  formValues: state.formValues,
149
+ tooltipState: state.tooltipState,
23
150
  };
24
- }
151
+ };
25
152
 
26
153
  export const selectState = ({ state }) => {
27
154
  return state;
28
- }
155
+ };
29
156
 
30
- export const selectFormValues = ({ state }) => {
31
- return state.formValues;
32
- }
157
+ export const selectFormValues = ({ state, props }) => {
158
+ const form = selectForm({ state, props });
33
159
 
34
- export const setState = (state) => {
35
- // do doSomething
36
- }
160
+ return pick(
161
+ state.formValues,
162
+ form.fields.map((field) => field.name),
163
+ );
164
+ };
165
+
166
+ export const getFormFieldValue = ({ state }, name) => {
167
+ return get(state.formValues, name);
168
+ };
37
169
 
38
- export const setDefaultValues = (state, defaultValues) => {
170
+ export const setFormValues = (state, defaultValues) => {
39
171
  state.formValues = defaultValues || {};
40
- }
172
+ };
41
173
 
42
- export const setFormFieldValue = (state, { fieldName, value }) => {
43
- state.formValues[fieldName] = value;
44
- }
174
+ export const setFormFieldValue = (state, { name, value, props }) => {
175
+ set(state.formValues, name, value);
176
+ // remove non visible values
177
+ const form = selectForm({ state, props });
178
+ const formValues = pick(
179
+ state.formValues,
180
+ form.fields.map((field) => field.name),
181
+ );
182
+ state.formValues = formValues;
183
+ };
45
184
 
185
+ export const showTooltip = (state, { x, y, content }) => {
186
+ state.tooltipState = {
187
+ open: true,
188
+ x: x,
189
+ y: y,
190
+ content: content
191
+ };
192
+ };
193
+
194
+ export const hideTooltip = (state) => {
195
+ state.tooltipState = {
196
+ ...state.tooltipState,
197
+ open: false
198
+ };
199
+ };
@@ -8,6 +8,8 @@ propsSchema:
8
8
  properties:
9
9
  defaultValues:
10
10
  type: object
11
+ context:
12
+ type: object
11
13
  form:
12
14
  type: object
13
15
  properties:
@@ -21,7 +23,7 @@ propsSchema:
21
23
  anyOf:
22
24
  - type: object
23
25
  properties:
24
- id:
26
+ name:
25
27
  type: string
26
28
  label:
27
29
  type: string
@@ -31,14 +33,19 @@ propsSchema:
31
33
  const: inputText
32
34
  placeholder:
33
35
  type: string
36
+ tooltip:
37
+ type: object
38
+ properties:
39
+ content:
40
+ type: string
34
41
  required:
35
- - id
42
+ - name
36
43
  - label
37
44
  - inputType
38
45
  additionalProperties: false
39
46
  - type: object
40
47
  properties:
41
- id:
48
+ name:
42
49
  type: string
43
50
  label:
44
51
  type: string
@@ -48,30 +55,39 @@ propsSchema:
48
55
  const: select
49
56
  placeholder:
50
57
  type: string
58
+ noClear:
59
+ type: boolean
60
+ addOption:
61
+ type: object
62
+ properties:
63
+ label:
64
+ type: string
51
65
  options:
52
66
  type: array
53
67
  items:
54
68
  type: object
55
69
  properties:
56
- id:
57
- type: string
58
70
  label:
59
71
  type: string
60
72
  value:
61
73
  type: any
62
74
  required:
63
- - id
64
75
  - label
65
76
  - value
77
+ tooltip:
78
+ type: object
79
+ properties:
80
+ content:
81
+ type: string
66
82
  required:
67
- - id
83
+ - name
68
84
  - label
69
85
  - inputType
70
86
  - options
71
87
  additionalProperties: false
72
88
  - type: object
73
89
  properties:
74
- id:
90
+ name:
75
91
  type: string
76
92
  label:
77
93
  type: string
@@ -81,14 +97,19 @@ propsSchema:
81
97
  const: colorPicker
82
98
  value:
83
99
  type: string
100
+ tooltip:
101
+ type: object
102
+ properties:
103
+ content:
104
+ type: string
84
105
  required:
85
- - id
106
+ - name
86
107
  - label
87
108
  - inputType
88
109
  additionalProperties: false
89
110
  - type: object
90
111
  properties:
91
- id:
112
+ name:
92
113
  type: string
93
114
  label:
94
115
  type: string
@@ -104,8 +125,119 @@ propsSchema:
104
125
  type: number
105
126
  value:
106
127
  type: number
128
+ tooltip:
129
+ type: object
130
+ properties:
131
+ content:
132
+ type: string
107
133
  required:
108
- - id
134
+ - name
135
+ - label
136
+ - inputType
137
+ additionalProperties: false
138
+ - type: object
139
+ properties:
140
+ name:
141
+ type: string
142
+ label:
143
+ type: string
144
+ description:
145
+ type: string
146
+ inputType:
147
+ const: slider-input
148
+ min:
149
+ type: number
150
+ max:
151
+ type: number
152
+ step:
153
+ type: number
154
+ value:
155
+ type: number
156
+ tooltip:
157
+ type: object
158
+ properties:
159
+ content:
160
+ type: string
161
+ required:
162
+ - name
163
+ - label
164
+ - inputType
165
+ additionalProperties: false
166
+ - type: object
167
+ properties:
168
+ name:
169
+ type: string
170
+ label:
171
+ type: string
172
+ description:
173
+ type: string
174
+ inputType:
175
+ const: image
176
+ width:
177
+ type: number
178
+ height:
179
+ type: number
180
+ placeholder:
181
+ type: string
182
+ tooltip:
183
+ type: object
184
+ properties:
185
+ content:
186
+ type: string
187
+ required:
188
+ - name
189
+ - label
190
+ - inputType
191
+ additionalProperties: false
192
+ - type: object
193
+ properties:
194
+ name:
195
+ type: string
196
+ label:
197
+ type: string
198
+ description:
199
+ type: string
200
+ inputType:
201
+ const: waveform
202
+ width:
203
+ type: number
204
+ height:
205
+ type: number
206
+ placeholder:
207
+ type: string
208
+ defaultValue:
209
+ type: object
210
+ waveformData:
211
+ type: object
212
+ tooltip:
213
+ type: object
214
+ properties:
215
+ content:
216
+ type: string
217
+ required:
218
+ - name
219
+ - label
220
+ - inputType
221
+ additionalProperties: false
222
+ - type: object
223
+ properties:
224
+ name:
225
+ type: string
226
+ label:
227
+ type: string
228
+ description:
229
+ type: string
230
+ inputType:
231
+ const: popover-input
232
+ placeholder:
233
+ type: string
234
+ tooltip:
235
+ type: object
236
+ properties:
237
+ content:
238
+ type: string
239
+ required:
240
+ - name
109
241
  - label
110
242
  - inputType
111
243
  additionalProperties: false
@@ -130,6 +262,12 @@ refs:
130
262
  eventListeners:
131
263
  click:
132
264
  handler: handleActionClick
265
+ tooltip-icon-*:
266
+ eventListeners:
267
+ mouseenter:
268
+ handler: handleTooltipMouseEnter
269
+ mouseleave:
270
+ handler: handleTooltipMouseLeave
133
271
  input-*:
134
272
  eventListeners:
135
273
  input-change:
@@ -138,6 +276,8 @@ refs:
138
276
  eventListeners:
139
277
  select-change:
140
278
  handler: handleSelectChange
279
+ add-option-selected:
280
+ handler: handleSelectAddOption
141
281
  colorpicker-*:
142
282
  eventListeners:
143
283
  colorpicker-change:
@@ -146,30 +286,74 @@ refs:
146
286
  eventListeners:
147
287
  slider-change:
148
288
  handler: handleSliderChange
289
+ slider-input-*:
290
+ eventListeners:
291
+ slider-input-value-change:
292
+ handler: handleSliderInputChange
293
+ image-*:
294
+ eventListeners:
295
+ click:
296
+ handler: handleImageClick
297
+ contextmenu:
298
+ handler: handleImageClick
299
+ waveform-*:
300
+ eventListeners:
301
+ click:
302
+ handler: handleWaveformClick
303
+ contextmenu:
304
+ handler: handleWaveformClick
305
+ popover-input-*:
306
+ eventListeners:
307
+ input-change:
308
+ handler: handlePopoverInputChange
149
309
 
150
310
  events:
151
311
  form-change: {}
312
+ extra-event: {}
313
+ action-click: {}
152
314
 
153
315
  template:
154
- - rtgl-view w=f h=f p=md g=lg ${containerAttrString}:
155
- - rtgl-view g=sm w=f:
156
- - rtgl-text s=lg: ${title}
157
- - rtgl-text c=mu-fg: ${description}
158
- - rtgl-view g=lg w=f:
159
- - $for field, i in fields:
160
- - rtgl-view g=md w=f:
161
- - rtgl-view g=sm:
162
- - rtgl-text: ${field.label}
163
- - rtgl-text s=sm c=mu-fg: ${field.description}
164
- - $if field.inputType == "inputText":
165
- - rtgl-input#input-${field.id} w=f placeholder=${field.placeholder}:
166
- - $if field.inputType == "select":
167
- - rtgl-select#select-${field.id} w=f .options=fields[${i}].options .placeholder=fields[${i}].placeholder .selectedValue=formValues[field.id]:
168
- - $if field.inputType == "colorPicker":
169
- - rtgl-color-picker#colorpicker-${field.id} value=${field.value}:
170
- - $if field.inputType == "slider":
171
- - rtgl-slider#slider-${field.id} min=${field.min} max=${field.max} step=${field.step} value=${field.value}:
172
- - rtgl-view g=sm w=f:
173
- - $for button, i in actions.buttons:
174
- - rtgl-view d=h ah=e g=sm w=f:
175
- - rtgl-button#action-${button.id}: ${button.content}
316
+ - rtgl-view w=f p=md g=lg ${containerAttrString}:
317
+ - rtgl-view g=sm w=f:
318
+ - rtgl-text s=lg: ${title}
319
+ - rtgl-text c=mu-fg: ${description}
320
+ - rtgl-view g=lg w=f:
321
+ - $for field, i in fields:
322
+ - rtgl-view g=md w=f:
323
+ - rtgl-view g=sm:
324
+ - rtgl-view d=h g=md av=c:
325
+ - rtgl-text: ${field.label}
326
+ - $if field.tooltip:
327
+ - rtgl-svg#tooltip-icon-${field.name} svg="info" wh=16 c=mu-fg cur=help ml=xs:
328
+ - rtgl-text s=sm c=mu-fg: ${field.description}
329
+ - $if field.inputType == "read-only-text":
330
+ - rtgl-text s=sm: ${field.defaultValue}
331
+ - $if field.inputType == "inputText":
332
+ - rtgl-input#input-${field.name} key=${key} w=f placeholder=${field.placeholder} value=${field.defaultValue}:
333
+ - $if field.inputType == "popover-input":
334
+ - rtgl-popover-input#popover-input-${field.name} label="${field.label}" .defaultValue=fields[${i}].defaultValue:
335
+ - $if field.inputType == "select":
336
+ - rtgl-select#select-${field.name} key=${key} w=f .options=fields[${i}].options .placeholder=fields[${i}].placeholder .selectedValue=fields[${i}].defaultValue ?no-clear=fields[${i}].noClear .addOption=fields[${i}].addOption:
337
+ - $if field.inputType == "colorPicker":
338
+ - rtgl-color-picker#colorpicker-${field.name} key=${key} value=${field.defaultValue}:
339
+ - $if field.inputType == "slider":
340
+ - rtgl-slider#slider-${field.name} key=${key} w=f min=${field.min} max=${field.max} step=${field.step} value=${field.defaultValue}:
341
+ - $if field.inputType == "slider-input":
342
+ - rtgl-slider-input#slider-input-${field.name} key=${key} w=f min=${field.min} max=${field.max} step=${field.step} defaultValue=${field.defaultValue}:
343
+ - $if field.inputType == "image" && field.imageSrc:
344
+ - rtgl-image#image-${field.name} src=${field.imageSrc} w=${field.width} h=${field.height} cur=p:
345
+ - $if field.inputType == "image" && !field.imageSrc:
346
+ - rtgl-view#image-${field.name} w=${field.width} h=${field.height} bc=ac bw=sm ah=c av=c cur=p p=md:
347
+ - rtgl-text c=mu-fg ta=c: ${field.placeholderText}
348
+ - $if field.inputType == "waveform" && field.waveformData:
349
+ - rtgl-waveform#waveform-${field.name} .waveformData=fields[${i}].waveformData w=${field.width} h=${field.height} cur=p:
350
+ - $if field.inputType == "waveform" && !field.waveformData:
351
+ - rtgl-view#waveform-${field.name} w=${field.width} h=${field.height} bc=ac bw=sm ah=c av=c cur=p p=md:
352
+ - rtgl-text c=mu-fg ta=c: ${field.placeholder}
353
+ - $if field.inputType == "slot":
354
+ - 'slot#slot-${field.slotName} name=${field.slot} style="display: contents;"':
355
+ - rtgl-view g=sm w=f:
356
+ - rtgl-view d=h ah=e g=sm w=f:
357
+ - $for button, i in actions.buttons:
358
+ - rtgl-button#action-${button.id}: ${button.content}
359
+ - rtgl-tooltip ?open=${tooltipState.open} x=${tooltipState.x} y=${tooltipState.y} placement="top" content="${tooltipState.content}":
@@ -57,7 +57,7 @@ const startListening = (contentContainer, deps) => {
57
57
  }
58
58
  };
59
59
 
60
- export const handleOnMount = (deps) => {
60
+ export const handleBeforeMount = (deps) => {
61
61
  const { attrs } = deps;
62
62
  requestAnimationFrame(() => {
63
63
  const targetElement = document.getElementById(attrs['target-id'])
@@ -0,0 +1,99 @@
1
+ export const handleBeforeMount = (deps) => {
2
+ const { store, props } = deps;
3
+
4
+ if (props.value !== undefined || props.defaultValue !== undefined) {
5
+ store.setValue(props.value || props.defaultValue || '');
6
+ }
7
+ }
8
+
9
+ export const handleOnUpdate = (changes, deps) => {
10
+ const { oldProps, newProps} = changes
11
+ const { store, props, render } = deps;
12
+
13
+ if (oldProps.defaultValue !== newProps.defaultValue) {
14
+ store.setValue(props.defaultValue || '');
15
+ }
16
+
17
+ render();
18
+ }
19
+
20
+ export const handleTextClick = (e, deps) => {
21
+ const { store, render, getRefIds, attrs } = deps;
22
+
23
+ const value = store.selectValue();
24
+ store.setTempValue(value)
25
+
26
+ store.openPopover({
27
+ position: {
28
+ x: e.currentTarget.getBoundingClientRect().left,
29
+ y: e.currentTarget.getBoundingClientRect().bottom,
30
+ }
31
+ });
32
+
33
+ const { input } = getRefIds();
34
+ input.elm.value = value;
35
+ render();
36
+
37
+ if (attrs['auto-focus']) {
38
+ setTimeout(() => {
39
+ input.elm.focus();
40
+ }, 50)
41
+ }
42
+ }
43
+
44
+ export const handlePopoverClose = (e, deps) => {
45
+ const { store, render } = deps;
46
+ store.closePopover();
47
+ render();
48
+ }
49
+
50
+ export const handleInputChange = (e, deps) => {
51
+ const { store, render, dispatchEvent } = deps;
52
+ const value = e.detail.value;
53
+
54
+ store.setTempValue(value);
55
+
56
+ dispatchEvent(new CustomEvent('temp-input-change', {
57
+ detail: { value },
58
+ bubbles: true
59
+ }));
60
+
61
+ render();
62
+ }
63
+
64
+ export const handleSubmitClick = (e, deps) => {
65
+ const { store, render, dispatchEvent, getRefIds } = deps;
66
+ const { input } = getRefIds()
67
+ const value = input.elm.value;
68
+
69
+ store.setValue(value)
70
+ store.closePopover();
71
+
72
+ dispatchEvent(new CustomEvent('input-change', {
73
+ detail: { value },
74
+ bubbles: true
75
+ }));
76
+
77
+ render();
78
+ }
79
+
80
+ export const handleInputKeydown = (e, deps) => {
81
+ const { store, render, dispatchEvent, getRefIds } = deps;
82
+
83
+ if (e.key === 'Enter') {
84
+ const { input } = getRefIds()
85
+ const value = input.elm.value;
86
+
87
+ store.closePopover();
88
+ // Dispatch custom event
89
+ dispatchEvent(new CustomEvent('input-change', {
90
+ detail: { value },
91
+ bubbles: true
92
+ }));
93
+
94
+ render();
95
+ } else if (e.key === 'Escape') {
96
+ store.closePopover();
97
+ render();
98
+ }
99
+ }