@rettangoli/ui 0.1.2-rc9 → 0.1.3

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 (66) hide show
  1. package/dist/rettangoli-iife-layout.min.js +128 -56
  2. package/dist/rettangoli-iife-ui.min.js +187 -66
  3. package/package.json +3 -2
  4. package/src/common.js +30 -2
  5. package/src/components/breadcrumb/breadcrumb.handlers.js +9 -0
  6. package/src/components/breadcrumb/breadcrumb.store.js +29 -0
  7. package/src/components/breadcrumb/breadcrumb.view.yaml +64 -0
  8. package/src/components/dropdownMenu/dropdownMenu.handlers.js +6 -6
  9. package/src/components/dropdownMenu/dropdownMenu.store.js +6 -18
  10. package/src/components/dropdownMenu/dropdownMenu.view.yaml +15 -13
  11. package/src/components/form/form.handlers.js +170 -33
  12. package/src/components/form/form.store.js +175 -21
  13. package/src/components/form/form.view.yaml +182 -27
  14. package/src/components/globalUi/globalUi.handlers.js +51 -0
  15. package/src/components/globalUi/globalUi.store.js +57 -0
  16. package/src/components/globalUi/globalUi.view.yaml +50 -0
  17. package/src/components/navbar/navbar.handlers.js +1 -1
  18. package/src/components/navbar/navbar.store.js +2 -2
  19. package/src/components/pageOutline/pageOutline.handlers.js +57 -17
  20. package/src/components/pageOutline/pageOutline.store.js +48 -3
  21. package/src/components/pageOutline/pageOutline.view.yaml +7 -5
  22. package/src/components/popoverInput/popoverInput.handlers.js +99 -0
  23. package/src/components/popoverInput/popoverInput.store.js +48 -0
  24. package/src/components/popoverInput/popoverInput.view.yaml +55 -0
  25. package/src/components/select/select.handlers.js +120 -12
  26. package/src/components/select/select.store.js +86 -20
  27. package/src/components/select/select.view.yaml +40 -10
  28. package/src/components/sidebar/sidebar.handlers.js +6 -6
  29. package/src/components/sidebar/sidebar.store.js +6 -6
  30. package/src/components/sidebar/sidebar.view.yaml +1 -1
  31. package/src/components/sliderInput/sliderInput.handlers.js +23 -6
  32. package/src/components/sliderInput/sliderInput.store.js +3 -2
  33. package/src/components/sliderInput/sliderInput.view.yaml +3 -2
  34. package/src/components/table/table.handlers.js +10 -10
  35. package/src/components/table/table.store.js +4 -4
  36. package/src/components/tabs/tabs.handlers.js +10 -0
  37. package/src/components/tabs/tabs.store.js +29 -0
  38. package/src/components/tabs/tabs.view.yaml +64 -0
  39. package/src/components/tooltip/tooltip.handlers.js +0 -0
  40. package/src/components/tooltip/tooltip.store.js +12 -0
  41. package/src/components/tooltip/tooltip.view.yaml +27 -0
  42. package/src/components/waveform/waveform.handlers.js +92 -0
  43. package/src/components/waveform/waveform.store.js +17 -0
  44. package/src/components/waveform/waveform.view.yaml +38 -0
  45. package/src/deps/createGlobalUI.js +39 -0
  46. package/src/entry-iife-layout.js +3 -0
  47. package/src/entry-iife-ui.js +4 -0
  48. package/src/index.js +7 -1
  49. package/src/primitives/button.js +10 -0
  50. package/src/primitives/colorPicker.js +13 -4
  51. package/src/primitives/dialog.js +254 -0
  52. package/src/primitives/image.js +4 -3
  53. package/src/primitives/input.js +17 -4
  54. package/src/primitives/popover.js +280 -0
  55. package/src/primitives/slider.js +14 -4
  56. package/src/primitives/svg.js +2 -0
  57. package/src/primitives/textarea.js +25 -1
  58. package/src/primitives/view.js +132 -13
  59. package/src/setup.js +7 -2
  60. package/src/styles/cursorStyles.js +38 -2
  61. package/src/components/dialog/dialog.handlers.js +0 -5
  62. package/src/components/dialog/dialog.store.js +0 -25
  63. package/src/components/dialog/dialog.view.yaml +0 -48
  64. package/src/components/popover/popover.handlers.js +0 -5
  65. package/src/components/popover/popover.store.js +0 -12
  66. package/src/components/popover/popover.view.yaml +0 -57
@@ -1,43 +1,82 @@
1
- export const INITIAL_STATE = Object.freeze({
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
+
26
+ export const createInitialState = () => Object.freeze({
2
27
  isOpen: false,
3
28
  position: {
4
29
  x: 0,
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';
14
-
37
+ export const selectViewData = ({ state, props, attrs }) => {
38
+ // Generate container attribute string
39
+ const containerAttrString = stringifyAttrs(attrs);
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 sv=true:
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}
@@ -1,15 +1,15 @@
1
- export const handleHeaderClick = (e, deps) => {
1
+ export const handleHeaderClick = (deps, event) => {
2
2
  const { store, dispatchEvent } = deps;
3
3
 
4
4
  let path;
5
5
 
6
6
  const header = store.selectHeader();
7
7
 
8
- if (e.currentTarget.id === 'header-label') {
8
+ if (event.currentTarget.id === 'header-label') {
9
9
  path = header.labelPath;
10
- } else if (e.currentTarget.id === 'header-image') {
10
+ } else if (event.currentTarget.id === 'header-image') {
11
11
  path = header.image.path;
12
- } else if (e.currentTarget.id === 'header') {
12
+ } else if (event.currentTarget.id === 'header') {
13
13
  path = header.path;
14
14
  }
15
15
 
@@ -22,9 +22,9 @@ export const handleHeaderClick = (e, deps) => {
22
22
  }));
23
23
  }
24
24
 
25
- export const handleItemClick = (e, deps) => {
25
+ export const handleItemClick = (deps, event) => {
26
26
  const { store, dispatchEvent } = deps;
27
- const id = e.currentTarget.id.replace('item-', '');
27
+ const id = event.currentTarget.id.replace('item-', '');
28
28
  const item = store.selectItem(id);
29
29
  dispatchEvent(new CustomEvent('itemClick', {
30
30
  detail: {
@@ -1,4 +1,4 @@
1
- export const INITIAL_STATE = Object.freeze({});
1
+ export const createInitialState = () => Object.freeze({});
2
2
 
3
3
  const blacklistedAttrs = ['id', 'class', 'style', 'slot'];
4
4
 
@@ -50,7 +50,7 @@ function flattenItems(items, selectedItemId = null) {
50
50
  return result;
51
51
  }
52
52
 
53
- export const toViewData = ({ state, props, attrs }) => {
53
+ export const selectViewData = ({ state, props, attrs }) => {
54
54
  const attrsHeader = attrs.header ? JSON.parse(decodeURIComponent(attrs.header)) : props.header;
55
55
  const attrsItems = attrs.items ? JSON.parse(decodeURIComponent(attrs.items)) : props.items;
56
56
  const selectedItemId = attrs.selectedItemId || props.selectedItemId;
@@ -81,17 +81,17 @@ export const toViewData = ({ state, props, attrs }) => {
81
81
  const firstLetterSize = mode === 'shrunk-lg' ? 'md' : 'sm';
82
82
  const showLabels = mode === 'full';
83
83
  const showGroupLabels = mode === 'full';
84
-
84
+
85
85
  // For items with icons in full mode, we need left alignment within the container
86
86
  // but the container itself should use flex-start alignment
87
87
  const itemContentAlign = mode === 'full' ? 'fs' : 'c';
88
-
88
+
89
89
  // Item container alignment - only set for shrunk modes, leave default for full mode
90
90
  const itemAlignAttr = mode === 'full' ? '' : `ah=${itemAlign}`;
91
-
91
+
92
92
  // Item width - for shrunk modes, make it square to constrain the highlight
93
93
  const itemWidth = mode === 'full' ? 'f' : itemHeight;
94
-
94
+
95
95
  // Header width - should match item width for alignment
96
96
  const headerWidth = itemWidth;
97
97
 
@@ -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:
@@ -1,17 +1,34 @@
1
- export const handleOnMount = (deps) => {
1
+ export const handleBeforeMount = (deps) => {
2
2
  const { store, attrs } = deps;
3
3
  store.setValue(attrs.defaultValue || 0);
4
- }
4
+ }
5
5
 
6
- export const handleValueChange = (e, deps) => {
6
+ export const handleOnUpdate = (changes, deps) => {
7
+ const { oldAttrs, newAttrs } = changes;
8
+ const { store, render, attrs } = deps;
9
+
10
+ // Reset when key changes
11
+ if (oldAttrs?.key !== newAttrs?.key && newAttrs?.key) {
12
+ const defaultValue = newAttrs?.defaultValue || attrs?.defaultValue || 0;
13
+ store.setValue(defaultValue);
14
+ render();
15
+ } else if (oldAttrs?.defaultValue !== newAttrs?.defaultValue) {
16
+ // Also reset when defaultValue changes
17
+ const defaultValue = newAttrs?.defaultValue || 0;
18
+ store.setValue(defaultValue);
19
+ render();
20
+ }
21
+ }
22
+
23
+ export const handleValueChange = (deps, event) => {
7
24
  const { store, render, dispatchEvent } = deps;
8
- const newValue = Number(e.detail.value);
25
+ const newValue = Number(event.detail.value);
9
26
 
10
27
  store.setValue(newValue);
11
-
28
+
12
29
  // Re-render to sync slider and input
13
30
  render();
14
-
31
+
15
32
  // Dispatch event for external listeners
16
33
  dispatchEvent(
17
34
  new CustomEvent("slider-input-value-change", {
@@ -1,9 +1,10 @@
1
- export const INITIAL_STATE = Object.freeze({
1
+ export const createInitialState = () => Object.freeze({
2
2
  value: 0
3
3
  });
4
4
 
5
- export const toViewData = ({ state, attrs }) => {
5
+ export const selectViewData = ({ state, attrs }) => {
6
6
  return {
7
+ key: attrs.key,
7
8
  value: state.value,
8
9
  w: attrs.w || '',
9
10
  min: attrs.min || 0,
@@ -37,5 +37,6 @@ events:
37
37
 
38
38
  template:
39
39
  - rtgl-view d=h av=c g=md w=${w}:
40
- - rtgl-slider#slider w=80% type=range min=${min} max=${max} step=${step} value=${value}:
41
- - rtgl-input#input w=20% type=number min=${min} max=${max} step=${step} value=${value}:
40
+ - rtgl-slider#slider key=${key} w=f type=range min=${min} max=${max} step=${step} value=${value}:
41
+ - rtgl-view w=84:
42
+ - rtgl-input#input key=${key} w=f type=number min=${min} max=${max} step=${step} value=${value}:
@@ -1,12 +1,12 @@
1
- export const handleOnMount = (deps) => {
1
+ export const handleBeforeMount = (deps) => {
2
2
  // No special initialization needed for basic table
3
3
  };
4
4
 
5
- export const handleRowClick = (e, deps) => {
5
+ export const handleRowClick = (deps, event) => {
6
6
  const { dispatchEvent, props } = deps;
7
- const rowIndex = parseInt(e.currentTarget.id.replace("row-", ""));
7
+ const rowIndex = parseInt(event.currentTarget.id.replace("row-", ""));
8
8
  const rowData = props.data?.rows?.[rowIndex];
9
-
9
+
10
10
  if (rowData) {
11
11
  dispatchEvent(
12
12
  new CustomEvent("row-click", {
@@ -19,11 +19,11 @@ export const handleRowClick = (e, deps) => {
19
19
  }
20
20
  };
21
21
 
22
- export const handleHeaderClick = (e, deps) => {
22
+ export const handleHeaderClick = (deps, event) => {
23
23
  const { store, render, dispatchEvent } = deps;
24
- const columnKey = e.currentTarget.id.replace("header-", "");
24
+ const columnKey = event.currentTarget.id.replace("header-", "");
25
25
  const currentSort = store.selectSortInfo();
26
-
26
+
27
27
  // Determine new sort direction
28
28
  let newDirection = 'asc';
29
29
  if (currentSort.column === columnKey) {
@@ -33,15 +33,15 @@ export const handleHeaderClick = (e, deps) => {
33
33
  newDirection = null; // Clear sort
34
34
  }
35
35
  }
36
-
36
+
37
37
  if (newDirection) {
38
38
  store.setSortColumn({ column: columnKey, direction: newDirection });
39
39
  } else {
40
40
  store.clearSort();
41
41
  }
42
-
42
+
43
43
  render();
44
-
44
+
45
45
  // Dispatch custom event for external handling
46
46
  dispatchEvent(
47
47
  new CustomEvent("header-click", {
@@ -1,4 +1,4 @@
1
- export const INITIAL_STATE = Object.freeze({
1
+ export const createInitialState = () => Object.freeze({
2
2
  sortColumn: null,
3
3
  sortDirection: null,
4
4
  });
@@ -23,10 +23,10 @@ const getNestedValue = (obj, path) => {
23
23
  return result;
24
24
  }
25
25
 
26
- export const toViewData = ({ state, props, attrs }) => {
26
+ export const selectViewData = ({ state, props, attrs }) => {
27
27
  const containerAttrString = stringifyAttrs(attrs);
28
28
  const data = props.data || { columns: [], rows: [] };
29
-
29
+
30
30
  // Transform rows to create cells array for easier template access
31
31
  const transformedRows = data.rows.map((row, rowIndex) => {
32
32
  const cells = data.columns.map(column => {
@@ -36,7 +36,7 @@ export const toViewData = ({ state, props, attrs }) => {
36
36
  value: value !== null && value !== undefined ? String(value) : ''
37
37
  };
38
38
  });
39
-
39
+
40
40
  return {
41
41
  index: rowIndex,
42
42
  cells: cells
@@ -0,0 +1,10 @@
1
+ export const handleClickItem = (deps, event) => {
2
+ const { dispatchEvent } = deps;
3
+ const id = event.currentTarget.dataset.id;
4
+
5
+ dispatchEvent(new CustomEvent('item-click', {
6
+ detail: {
7
+ id
8
+ }
9
+ }));
10
+ }
@@ -0,0 +1,29 @@
1
+ export const createInitialState = () => Object.freeze({});
2
+
3
+ const blacklistedAttrs = ['id', 'class', 'style', 'slot'];
4
+
5
+ const stringifyAttrs = (attrs) => {
6
+ return Object.entries(attrs).filter(([key]) => !blacklistedAttrs.includes(key)).map(([key, value]) => `${key}=${value}`).join(' ');
7
+ }
8
+
9
+ export const selectViewData = ({ state, props, attrs }) => {
10
+ const containerAttrString = stringifyAttrs(attrs);
11
+
12
+ const items = props.items || [];
13
+ const selectedTab = attrs['selected-tab'];
14
+
15
+ // Mark selected tab with styling
16
+ const itemsWithSelection = items.map(item => ({
17
+ ...item,
18
+ isSelected: item.id === selectedTab,
19
+ bgColor: item.id === selectedTab ? 'ac' : '',
20
+ borderColor: item.id === selectedTab ? '' : 'tr',
21
+ textColor: item.id === selectedTab ? '' : 'mu-fg'
22
+ }));
23
+
24
+ return {
25
+ containerAttrString,
26
+ items: itemsWithSelection,
27
+ selectedTab
28
+ };
29
+ }
@@ -0,0 +1,64 @@
1
+ elementName: rtgl-tabs
2
+
3
+ viewDataSchema:
4
+ type: object
5
+ properties:
6
+ containerAttrString:
7
+ type: string
8
+ items:
9
+ type: array
10
+ items:
11
+ type: object
12
+ properties:
13
+ label:
14
+ type: string
15
+ id:
16
+ type: string
17
+ isSelected:
18
+ type: boolean
19
+ bgColor:
20
+ type: string
21
+ textColor:
22
+ type: string
23
+ borderColor:
24
+ type: string
25
+ selectedTab:
26
+ type: string
27
+
28
+ propsSchema:
29
+ type: object
30
+ properties:
31
+ items:
32
+ type: array
33
+ items:
34
+ type: object
35
+ properties:
36
+ label:
37
+ type: string
38
+ id:
39
+ type: string
40
+
41
+ attrsSchema:
42
+ type: object
43
+ properties:
44
+ selected-tab:
45
+ type: string
46
+
47
+ refs:
48
+ tab-*:
49
+ eventListeners:
50
+ click:
51
+ handler: handleClickItem
52
+
53
+ events:
54
+ item-click:
55
+ type: object
56
+ properties:
57
+ id:
58
+ type: string
59
+
60
+ template:
61
+ - rtgl-view d=h g=sm bgc=mu p=sm br=lg ${containerAttrString}:
62
+ - $for item in items:
63
+ - rtgl-view#tab-${item.id} data-id=${item.id} cur=p bgc=${item.bgColor} bw=xs bc=${item.borderColor} pv=md ph=lg br=lg:
64
+ - rtgl-text s=sm c=${item.textColor}: "${item.label}"
File without changes
@@ -0,0 +1,12 @@
1
+ export const createInitialState = () => Object.freeze({
2
+ });
3
+
4
+ export const selectViewData = ({ attrs }) => {
5
+ return {
6
+ open: !!attrs.open,
7
+ x: attrs.x || 0,
8
+ y: attrs.y || 0,
9
+ placement: attrs.placement || 'top',
10
+ content: attrs.content || ''
11
+ };
12
+ }
@@ -0,0 +1,27 @@
1
+ elementName: rtgl-tooltip
2
+
3
+ viewDataSchema:
4
+ type: object
5
+
6
+ attrsSchema:
7
+ type: object
8
+ properties:
9
+ open:
10
+ type: string
11
+ x:
12
+ type: string
13
+ y:
14
+ type: string
15
+ placement:
16
+ type: string
17
+ content:
18
+ type: string
19
+
20
+ refs:
21
+ popover:
22
+
23
+ template:
24
+ - rtgl-popover#popover ?open=${open} x=${x} y=${y} placement=${placement} no-overlay:
25
+ - rtgl-view slot=content bgc=background bc=border br=md p=sm ah=c av=c:
26
+ - rtgl-text ta=c s=sm c=foreground: ${content}
27
+