@rettangoli/ui 0.1.2-rc3 → 0.1.2-rc31

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 (56) 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 +57 -17
  17. package/src/components/pageOutline/pageOutline.store.js +46 -1
  18. package/src/components/pageOutline/pageOutline.view.yaml +7 -5
  19. package/src/components/popoverInput/popoverInput.handlers.js +99 -0
  20. package/src/components/popoverInput/popoverInput.store.js +48 -0
  21. package/src/components/popoverInput/popoverInput.view.yaml +55 -0
  22. package/src/components/select/select.handlers.js +116 -11
  23. package/src/components/select/select.store.js +84 -18
  24. package/src/components/select/select.view.yaml +40 -10
  25. package/src/components/sidebar/sidebar.view.yaml +1 -1
  26. package/src/components/sliderInput/sliderInput.handlers.js +41 -0
  27. package/src/components/sliderInput/sliderInput.store.js +18 -0
  28. package/src/components/sliderInput/sliderInput.view.yaml +42 -0
  29. package/src/components/table/table.handlers.js +1 -1
  30. package/src/components/tabs/tabs.handlers.js +10 -0
  31. package/src/components/tabs/tabs.store.js +29 -0
  32. package/src/components/tabs/tabs.view.yaml +64 -0
  33. package/src/components/tooltip/tooltip.handlers.js +0 -0
  34. package/src/components/tooltip/tooltip.store.js +12 -0
  35. package/src/components/tooltip/tooltip.view.yaml +27 -0
  36. package/src/components/waveform/waveform.handlers.js +92 -0
  37. package/src/components/waveform/waveform.store.js +17 -0
  38. package/src/components/waveform/waveform.view.yaml +38 -0
  39. package/src/entry-iife-layout.js +3 -0
  40. package/src/entry-iife-ui.js +4 -0
  41. package/src/index.js +5 -1
  42. package/src/primitives/button.js +10 -0
  43. package/src/primitives/colorPicker.js +9 -0
  44. package/src/primitives/dialog.js +254 -0
  45. package/src/primitives/input.js +41 -11
  46. package/src/primitives/popover.js +280 -0
  47. package/src/primitives/slider.js +18 -9
  48. package/src/primitives/svg.js +2 -0
  49. package/src/primitives/textarea.js +25 -1
  50. package/src/styles/cursorStyles.js +38 -2
  51. package/src/components/dialog/dialog.handlers.js +0 -5
  52. package/src/components/dialog/dialog.store.js +0 -25
  53. package/src/components/dialog/dialog.view.yaml +0 -44
  54. package/src/components/popover/popover.handlers.js +0 -5
  55. package/src/components/popover/popover.store.js +0 -12
  56. package/src/components/popover/popover.view.yaml +0 -57
@@ -5,11 +5,56 @@ export const INITIAL_STATE = Object.freeze({
5
5
  });
6
6
 
7
7
  export const toViewData = ({ state }) => {
8
+ // Find all parent IDs for the current active item
9
+ const getActiveParentIds = (items, currentId) => {
10
+ const activeParentIds = new Set();
11
+ const currentIndex = items.findIndex(item => item.id === currentId);
12
+
13
+ if (currentIndex === -1) return activeParentIds;
14
+
15
+ const currentLevel = items[currentIndex].level;
16
+
17
+ // Look backwards for all parents (items with lower level)
18
+ for (let i = currentIndex - 1; i >= 0; i--) {
19
+ if (items[i].level < currentLevel) {
20
+ // This is a parent - mark all ancestors
21
+ let ancestorLevel = items[i].level;
22
+ activeParentIds.add(items[i].id);
23
+
24
+ // Continue looking for grandparents
25
+ for (let j = i - 1; j >= 0; j--) {
26
+ if (items[j].level < ancestorLevel) {
27
+ activeParentIds.add(items[j].id);
28
+ ancestorLevel = items[j].level;
29
+ }
30
+ }
31
+ break; // Found the immediate parent chain
32
+ }
33
+ }
34
+
35
+ return activeParentIds;
36
+ };
37
+
38
+ const activeParentIds = getActiveParentIds(state.items, state.currentId);
39
+
8
40
  return {
9
41
  items: state.items.map((item) => {
42
+ const mlValues = {
43
+ 1: '0',
44
+ 2: '12px',
45
+ 3: '24px',
46
+ 4: '32px'
47
+ };
48
+
49
+ const isDirectlyActive = item.id === state.currentId;
50
+ const isParentActive = activeParentIds.has(item.id);
51
+ const active = isDirectlyActive || isParentActive;
52
+
10
53
  return {
11
54
  ...item,
12
- c: item.id === state.currentId ? 'fg' : 'mu-fg'
55
+ c: active ? 'fg' : 'mu-fg',
56
+ ml: mlValues[item.level] || '',
57
+ bc: active ? "fg" : "mu-fg"
13
58
  }
14
59
  }),
15
60
  currentId: state.currentId
@@ -27,8 +27,10 @@ events:
27
27
  type: object
28
28
 
29
29
  template:
30
- - rtgl-view h=f w=272:
31
- - rtgl-view w=f g=sm mt=xl:
32
- - $for item, i in items:
33
- - rtgl-view pv=xs av=c href=${item.href}:
34
- - rtgl-text s=sm c=${item.c} h-c=fg: ${item.title}
30
+ - rtgl-view h=f w=272 pr=md:
31
+ - rtgl-view w=f mt=xl:
32
+ - $for item, i in items:
33
+ - rtgl-view d=h bwl=xs bc="${item.bc}" pv=sm av=c href=${item.href} pl=md:
34
+ - rtgl-view w=${item.ml}:
35
+ - rtgl-text s=sm c=${item.c} h-c=fg: ${item.title}
36
+
@@ -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
+ }
@@ -0,0 +1,48 @@
1
+ export const INITIAL_STATE = Object.freeze({
2
+ isOpen: false,
3
+ position: {
4
+ x: 0,
5
+ y: 0,
6
+ },
7
+ value: '',
8
+ tempValue: '',
9
+ });
10
+
11
+ export const toViewData = ({ attrs, state, props }) => {
12
+ // Use state's current value if it has been modified, otherwise use props
13
+ const value = state.value || '-';
14
+
15
+ return {
16
+ isOpen: state.isOpen,
17
+ position: state.position,
18
+ value: value ?? '-',
19
+ tempValue: state.tempValue,
20
+ placeholder: props.placeholder ?? '',
21
+ label: attrs.label,
22
+ };
23
+ }
24
+
25
+ export const setTempValue = (state, value) => {
26
+ state.tempValue = value;
27
+ }
28
+
29
+ export const openPopover = (state, payload) => {
30
+ const { position } = payload;
31
+ state.position = position;
32
+ state.isOpen = true;
33
+ // Reset the current value to match the display value when opening
34
+ state.hasUnsavedChanges = false;
35
+ }
36
+
37
+ export const closePopover = (state) => {
38
+ state.isOpen = false;
39
+ state.tempValue = '';
40
+ }
41
+
42
+ export const setValue = (state, value) => {
43
+ state.value = value;
44
+ }
45
+
46
+ export const selectValue = ({ state }) => {
47
+ return state.value;
48
+ }
@@ -0,0 +1,55 @@
1
+ elementName: rtgl-popover-input
2
+
3
+ viewDataSchema:
4
+ type: object
5
+
6
+ attrsSchema:
7
+ type: object
8
+ properties:
9
+ auto-focus:
10
+ type: boolean
11
+
12
+ propsSchema:
13
+ type: object
14
+ properties:
15
+ value:
16
+ type: string
17
+ defaultValue:
18
+ type: string
19
+ placeholder:
20
+ type: string
21
+ onChange:
22
+ type: function
23
+
24
+ refs:
25
+ text-display:
26
+ eventListeners:
27
+ click:
28
+ handler: handleTextClick
29
+ popover:
30
+ eventListeners:
31
+ close:
32
+ handler: handlePopoverClose
33
+ input:
34
+ eventListeners:
35
+ input-change:
36
+ handler: handleInputChange
37
+ keydown:
38
+ handler: handleInputKeydown
39
+ submit:
40
+ eventListeners:
41
+ click:
42
+ handler: handleSubmitClick
43
+
44
+ events:
45
+ input-change: {}
46
+
47
+ template:
48
+ - rtgl-view#text-display w=f cur=p:
49
+ - rtgl-text: ${value}
50
+ - rtgl-popover#popover ?open=${isOpen} x=${position.x} y=${position.y}:
51
+ - rtgl-view g=md w=240 slot=content bgc=background br=md:
52
+ - rtgl-text: ${label}
53
+ - rtgl-input#input w=f placeholder=${placeholder}:
54
+ - rtgl-view w=f ah=e:
55
+ - rtgl-button#submit: Submit
@@ -1,26 +1,64 @@
1
+ import { deepEqual } from '../../common.js';
1
2
 
2
- export const handleOnMount = (deps) => {
3
+ export const handleBeforeMount = (deps) => {
3
4
  const { store, props, render } = deps;
4
-
5
+
5
6
  if (props.selectedValue !== null && props.selectedValue !== undefined && props.options) {
6
- const selectedOption = props.options.find(opt => opt.value === props.selectedValue);
7
+ const selectedOption = props.options.find(opt => deepEqual(opt.value, props.selectedValue));
7
8
  if (selectedOption) {
8
- store.update((state) => {
9
- state.selectedValue = selectedOption.value;
10
- state.selectedLabel = selectedOption.label;
11
- });
9
+ store.updateSelectOption(selectedOption);
12
10
  render();
13
11
  }
14
12
  }
15
13
  }
16
14
 
15
+ export const handleOnUpdate = (changes, deps) => {
16
+ const { oldAttrs, newAttrs, oldProps, newProps } = changes;
17
+ const { store, props, render } = deps;
18
+
19
+ // Check if key changed
20
+ if (oldAttrs?.key !== newAttrs?.key && newAttrs?.key) {
21
+ // Clear current state using store action
22
+ store.resetSelection();
23
+
24
+ // Re-apply the prop value if available
25
+ const selectedValue = newProps?.selectedValue || props?.selectedValue;
26
+ const options = newProps?.options || props?.options;
27
+
28
+ if (selectedValue !== null && selectedValue !== undefined && options) {
29
+ const selectedOption = options.find(opt => deepEqual(opt.value, selectedValue));
30
+ if (selectedOption) {
31
+ store.updateSelectOption(selectedOption);
32
+ }
33
+ }
34
+ render();
35
+ }
36
+ }
37
+
17
38
  export const handleButtonClick = (e, deps) => {
18
- const { store, render, getRefIds } = deps;
39
+ const { store, render, getRefIds, props } = deps;
40
+
41
+ const button = getRefIds()['select-button'].elm;
42
+
43
+ // Get first child's bounding rectangle (since button has display: contents)
44
+ const firstChild = button.firstElementChild;
45
+ const rect = firstChild ? firstChild.getBoundingClientRect() : button.getBoundingClientRect();
46
+
47
+ // Find the index of the currently selected option
48
+ const storeSelectedValue = store.selectSelectedValue();
49
+ const currentValue = storeSelectedValue !== null ? storeSelectedValue : props.selectedValue;
50
+ let selectedIndex = null;
51
+ if (currentValue !== null && currentValue !== undefined && props.options) {
52
+ selectedIndex = props.options.findIndex(opt => deepEqual(opt.value, currentValue));
53
+ if (selectedIndex === -1) selectedIndex = null;
54
+ }
55
+
19
56
  store.openOptionsPopover({
20
57
  position: {
21
- y: e.clientY,
22
- x: e.clientX,
23
- }
58
+ y: rect.bottom + 12, // Bottom edge of button
59
+ x: rect.left - 24, // Left edge of button
60
+ },
61
+ selectedIndex
24
62
  })
25
63
  render();
26
64
  }
@@ -56,6 +94,73 @@ export const handleOptionClick = (e, deps) => {
56
94
  detail: { selectedValue: option.value },
57
95
  bubbles: true
58
96
  }));
97
+
98
+ render();
99
+ }
100
+
101
+ export const handleOptionMouseEnter = (e, deps) => {
102
+ const { store, render } = deps;
103
+ const id = parseInt(e.currentTarget.id.replace('option-', ''));
104
+ store.setHoveredOption(id);
105
+ render();
106
+ }
107
+
108
+ export const handleOptionMouseLeave = (e, deps) => {
109
+ const { store, render } = deps;
110
+ store.clearHoveredOption();
111
+ render();
112
+ }
113
+
114
+ export const handleClearClick = (e, deps) => {
115
+ const { store, render, dispatchEvent, props } = deps;
116
+
117
+ e.stopPropagation();
118
+
119
+ // Clear the internal state
120
+ store.clearSelectedValue();
121
+
122
+ // Call onChange if provided
123
+ if (props.onChange && typeof props.onChange === 'function') {
124
+ props.onChange(undefined);
125
+ }
126
+
127
+ // Dispatch custom event for backward compatibility
128
+ dispatchEvent(new CustomEvent('option-selected', {
129
+ detail: { value: undefined, label: undefined },
130
+ bubbles: true
131
+ }));
132
+
133
+ // Also dispatch select-change event to match form's event listener pattern
134
+ dispatchEvent(new CustomEvent('select-change', {
135
+ detail: { selectedValue: undefined },
136
+ bubbles: true
137
+ }));
138
+
139
+ render();
140
+ }
141
+
142
+ export const handleAddOptionClick = (e, deps) => {
143
+ const { store, render, dispatchEvent } = deps;
59
144
 
145
+ // Close the popover
146
+ store.closeOptionsPopover();
147
+
148
+ // Dispatch custom event for add option (no detail)
149
+ dispatchEvent(new CustomEvent('add-option-selected', {
150
+ bubbles: true
151
+ }));
152
+
153
+ render();
154
+ }
155
+
156
+ export const handleAddOptionMouseEnter = (e, deps) => {
157
+ const { store, render } = deps;
158
+ store.setHoveredAddOption(true);
159
+ render();
160
+ }
161
+
162
+ export const handleAddOptionMouseLeave = (e, deps) => {
163
+ const { store, render } = deps;
164
+ store.setHoveredAddOption(false);
60
165
  render();
61
166
  }
@@ -1,3 +1,28 @@
1
+ import { deepEqual } from '../../common.js';
2
+
3
+ // Attributes that should not be passed through to the container
4
+ // These are either handled internally or have special meaning
5
+ const blacklistedAttrs = [
6
+ "id",
7
+ "class",
8
+ "style",
9
+ "slot",
10
+ // Select-specific props that are handled separately
11
+ "placeholder",
12
+ "selectedValue",
13
+ "selected-value",
14
+ "onChange",
15
+ "on-change",
16
+ "options"
17
+ ];
18
+
19
+ const stringifyAttrs = (attrs) => {
20
+ return Object.entries(attrs || {})
21
+ .filter(([key]) => !blacklistedAttrs.includes(key))
22
+ .map(([key, value]) => `${key}=${value}`)
23
+ .join(" ");
24
+ };
25
+
1
26
  export const INITIAL_STATE = Object.freeze({
2
27
  isOpen: false,
3
28
  position: {
@@ -5,39 +30,53 @@ export const INITIAL_STATE = Object.freeze({
5
30
  y: 0,
6
31
  },
7
32
  selectedValue: null,
8
- selectedLabel: null,
33
+ hoveredOptionId: null,
34
+ hoveredAddOption: false,
9
35
  });
10
36
 
11
- export const toViewData = ({ state, props }) => {
12
- // Calculate display label
13
- let displayLabel = props.placeholder || 'Select an option';
37
+ export const toViewData = ({ state, props, attrs }) => {
38
+ // Generate container attribute string
39
+ const containerAttrString = stringifyAttrs(attrs);
14
40
 
15
41
  // Use state's selected value if available, otherwise use props.selectedValue
16
42
  const currentValue = state.selectedValue !== null ? state.selectedValue : props.selectedValue;
17
-
43
+
44
+ // Calculate display label from value
45
+ let displayLabel = props.placeholder || 'Select an option';
46
+ let isPlaceholderLabel = true;
18
47
  if (currentValue !== null && currentValue !== undefined && props.options) {
19
- const selectedOption = props.options.find(opt => opt.value === currentValue);
48
+ const selectedOption = props.options.find(opt => deepEqual(opt.value, currentValue));
20
49
  if (selectedOption) {
21
50
  displayLabel = selectedOption.label;
51
+ isPlaceholderLabel = false;
22
52
  }
23
- } else if (state.selectedLabel) {
24
- displayLabel = state.selectedLabel;
25
53
  }
26
-
54
+
27
55
  // Map options to include isSelected flag and computed background color
28
- const optionsWithSelection = (props.options || []).map(option => ({
29
- ...option,
30
- isSelected: option.value === currentValue,
31
- bgc: option.value === currentValue ? 'mu' : ''
32
- }));
33
-
56
+ const optionsWithSelection = (props.options || []).map((option, index) => {
57
+ const isSelected = deepEqual(option.value, currentValue);
58
+ const isHovered = state.hoveredOptionId === index;
59
+ return {
60
+ ...option,
61
+ isSelected,
62
+ bgc: isHovered ? 'ac' : (isSelected ? 'mu' : '')
63
+ };
64
+ });
65
+
34
66
  return {
67
+ containerAttrString,
35
68
  isOpen: state.isOpen,
36
69
  position: state.position,
37
70
  options: optionsWithSelection,
38
71
  selectedValue: currentValue,
39
72
  selectedLabel: displayLabel,
40
- placeholder: props.placeholder || 'Select an option'
73
+ selectedLabelColor: isPlaceholderLabel ? "mu-fg" : "fg",
74
+ placeholder: props.placeholder || 'Select an option',
75
+ hasValue: currentValue !== null && currentValue !== undefined,
76
+ showClear: !attrs['no-clear'] && !props['no-clear'] && (currentValue !== null && currentValue !== undefined),
77
+ showAddOption: !!props.addOption,
78
+ addOptionLabel: props.addOption?.label ? `+ ${props.addOption.label}` : '+ Add',
79
+ addOptionBgc: state.hoveredAddOption ? 'ac' : ''
41
80
  };
42
81
  }
43
82
 
@@ -45,10 +84,18 @@ export const selectState = ({ state }) => {
45
84
  return state;
46
85
  }
47
86
 
87
+ export const selectSelectedValue = ({ state }) => {
88
+ return state.selectedValue;
89
+ }
90
+
48
91
  export const openOptionsPopover = (state, payload) => {
49
- const { position } = payload;
92
+ const { position, selectedIndex } = payload;
50
93
  state.position = position;
51
94
  state.isOpen = true;
95
+ // Set hoveredOptionId to the selected option's index if available
96
+ if (selectedIndex !== undefined && selectedIndex !== null) {
97
+ state.hoveredOptionId = selectedIndex;
98
+ }
52
99
  }
53
100
 
54
101
  export const closeOptionsPopover = (state) => {
@@ -57,9 +104,28 @@ export const closeOptionsPopover = (state) => {
57
104
 
58
105
  export const updateSelectOption = (state, option) => {
59
106
  state.selectedValue = option.value;
60
- state.selectedLabel = option.label;
61
107
  state.isOpen = false;
62
108
  }
63
109
 
110
+ export const resetSelection = (state) => {
111
+ state.selectedValue = undefined;
112
+ }
113
+
114
+ export const setHoveredOption = (state, optionId) => {
115
+ state.hoveredOptionId = optionId;
116
+ }
117
+
118
+ export const clearHoveredOption = (state) => {
119
+ state.hoveredOptionId = null;
120
+ }
121
+
122
+ export const clearSelectedValue = (state) => {
123
+ state.selectedValue = undefined;
124
+ }
125
+
126
+ export const setHoveredAddOption = (state, isHovered) => {
127
+ state.hoveredAddOption = isHovered;
128
+ }
129
+
64
130
 
65
131
 
@@ -11,8 +11,6 @@ propsSchema:
11
11
  items:
12
12
  type: object
13
13
  properties:
14
- id:
15
- type: string
16
14
  label:
17
15
  type: string
18
16
  value:
@@ -23,28 +21,60 @@ propsSchema:
23
21
  type: string
24
22
  onChange:
25
23
  type: function
24
+ no-clear:
25
+ type: boolean
26
+ addOption:
27
+ type: object
28
+ properties:
29
+ label:
30
+ type: string
26
31
 
27
32
  refs:
28
33
  select-button:
29
34
  eventListeners:
30
35
  click:
31
36
  handler: handleButtonClick
37
+ clear-button:
38
+ eventListeners:
39
+ click:
40
+ handler: handleClearClick
32
41
  popover:
33
42
  eventListeners:
34
- click-overlay:
43
+ close:
35
44
  handler: handleClickOptionsPopoverOverlay
36
45
  option-*:
37
46
  eventListeners:
38
47
  click:
39
48
  handler: handleOptionClick
49
+ mouseenter:
50
+ handler: handleOptionMouseEnter
51
+ mouseleave:
52
+ handler: handleOptionMouseLeave
53
+ option-add:
54
+ eventListeners:
55
+ click:
56
+ handler: handleAddOptionClick
57
+ mouseenter:
58
+ handler: handleAddOptionMouseEnter
59
+ mouseleave:
60
+ handler: handleAddOptionMouseLeave
40
61
 
41
62
  events: {}
42
63
 
43
64
  template:
44
- - rtgl-button#select-button v=ol:
45
- - ${selectedLabel}
46
- - rtgl-popover#popover .isOpen=isOpen .position=position:
47
- - rtgl-view wh=300 g=xs slot=content bgc=background br=md:
48
- - $for option, i in options:
49
- - rtgl-view#option-${i} w=f h-bgc=ac ph=lg pv=md cur=p br=md bgc=${option.bgc}:
50
- - rtgl-text: ${option.label}
65
+ - rtgl-button#select-button v=ol ${containerAttrString}:
66
+ - rtgl-view d=h av=c w=f:
67
+ - rtgl-text c=${selectedLabelColor}: ${selectedLabel}
68
+ - rtgl-view mh=md flex=1:
69
+ - $if showClear:
70
+ - rtgl-svg#clear-button mr=md svg=x wh=16 c=mu-fg cur=p:
71
+ - rtgl-svg svg=chevronDown wh=16 c=mu-fg:
72
+ - rtgl-popover#popover ?open=${isOpen} x=${position.x} y=${position.y} placement=right-start:
73
+ - rtgl-view wh=300 g=xs slot=content bgc=background br=md sv=true:
74
+ - $for option, i in options:
75
+ - rtgl-view#option-${i} w=f ph=lg pv=md cur=p br=md bgc=${option.bgc}:
76
+ - rtgl-text: ${option.label}
77
+ - $if showAddOption:
78
+ - rtgl-view w=f bw=xs bc=mu-bg bt=sm:
79
+ - rtgl-view#option-add w=f ph=lg pv=md cur=p br=md bgc=${addOptionBgc}:
80
+ - rtgl-text c=ac: ${addOptionLabel}
@@ -174,7 +174,7 @@ template:
174
174
  $else:
175
175
  - rtgl-view mt=md h=1 bgc=mu-bg:
176
176
  $else:
177
- - rtgl-view#item-${item.id} ${item.hrefAttr} h=${itemHeight} av=c ${itemAlignAttr} ph=${itemPadding} w=${itemWidth} h-bgc=${item.itemHoverBgc} br=lg bgc=${item.itemBgc} cur=p title="${item.title}":
177
+ - rtgl-view#item-${item.id} ${item.hrefAttr} h=${itemHeight} av=c ${itemAlignAttr} ph=${itemPadding} w=${itemWidth} h-bgc=${item.itemHoverBgc} br=lg bgc=${item.itemBgc} cur=p:
178
178
  - $if item.icon:
179
179
  - $if showLabels:
180
180
  - rtgl-view d=h ah=${itemContentAlign} g=sm: