@rettangoli/ui 0.1.2-rc2 → 0.1.2-rc21

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 (45) hide show
  1. package/dist/rettangoli-iife-layout.min.js +102 -32
  2. package/dist/rettangoli-iife-ui.min.js +182 -69
  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/components/breadcrumb/breadcrumb.handlers.js +9 -0
  7. package/src/components/breadcrumb/breadcrumb.store.js +29 -0
  8. package/src/components/breadcrumb/breadcrumb.view.yaml +64 -0
  9. package/src/components/dropdownMenu/dropdownMenu.handlers.js +4 -4
  10. package/src/components/dropdownMenu/dropdownMenu.store.js +5 -17
  11. package/src/components/dropdownMenu/dropdownMenu.view.yaml +15 -13
  12. package/src/components/form/form.handlers.js +133 -24
  13. package/src/components/form/form.store.js +125 -23
  14. package/src/components/form/form.view.yaml +139 -29
  15. package/src/components/pageOutline/pageOutline.handlers.js +1 -1
  16. package/src/components/popoverInput/popoverInput.handlers.js +99 -0
  17. package/src/components/popoverInput/popoverInput.store.js +48 -0
  18. package/src/components/popoverInput/popoverInput.view.yaml +55 -0
  19. package/src/components/select/select.handlers.js +2 -5
  20. package/src/components/select/select.view.yaml +3 -3
  21. package/src/components/sidebar/sidebar.view.yaml +1 -1
  22. package/src/components/sliderInput/sliderInput.handlers.js +24 -0
  23. package/src/components/sliderInput/sliderInput.store.js +17 -0
  24. package/src/components/sliderInput/sliderInput.view.yaml +42 -0
  25. package/src/components/table/table.handlers.js +1 -1
  26. package/src/components/tabs/tabs.handlers.js +10 -0
  27. package/src/components/tabs/tabs.store.js +29 -0
  28. package/src/components/tabs/tabs.view.yaml +64 -0
  29. package/src/components/waveform/waveform.handlers.js +92 -0
  30. package/src/components/waveform/waveform.store.js +17 -0
  31. package/src/components/waveform/waveform.view.yaml +38 -0
  32. package/src/entry-iife-layout.js +3 -0
  33. package/src/entry-iife-ui.js +4 -0
  34. package/src/index.js +5 -1
  35. package/src/primitives/dialog.js +208 -0
  36. package/src/primitives/input.js +32 -11
  37. package/src/primitives/popover.js +275 -0
  38. package/src/primitives/slider.js +8 -9
  39. package/src/styles/viewStyles.js +1 -0
  40. package/src/components/dialog/dialog.handlers.js +0 -5
  41. package/src/components/dialog/dialog.store.js +0 -25
  42. package/src/components/dialog/dialog.view.yaml +0 -44
  43. package/src/components/popover/popover.handlers.js +0 -5
  44. package/src/components/popover/popover.store.js +0 -12
  45. package/src/components/popover/popover.view.yaml +0 -57
@@ -0,0 +1,275 @@
1
+ import { css } from "../common.js";
2
+
3
+ class RettangoliPopoverElement extends HTMLElement {
4
+ static styleSheet = null;
5
+
6
+ static initializeStyleSheet() {
7
+ if (!RettangoliPopoverElement.styleSheet) {
8
+ RettangoliPopoverElement.styleSheet = new CSSStyleSheet();
9
+ RettangoliPopoverElement.styleSheet.replaceSync(css`
10
+ :host {
11
+ display: contents;
12
+ }
13
+
14
+ .popover-overlay {
15
+ position: fixed;
16
+ top: 0;
17
+ left: 0;
18
+ width: 100vw;
19
+ height: 100vh;
20
+ z-index: 999;
21
+ display: none;
22
+ }
23
+
24
+ .popover-container {
25
+ position: fixed;
26
+ z-index: 1000;
27
+ display: none;
28
+ outline: none;
29
+ }
30
+
31
+ :host([open]) .popover-overlay {
32
+ display: block;
33
+ }
34
+
35
+ :host([open]) .popover-container {
36
+ display: block;
37
+ visibility: hidden;
38
+ }
39
+
40
+ :host([open][positioned]) .popover-container {
41
+ visibility: visible;
42
+ }
43
+
44
+ slot[name="content"] {
45
+ display: block;
46
+ background-color: var(--muted);
47
+ border: 1px solid var(--border);
48
+ border-radius: var(--border-radius-md);
49
+ padding: var(--spacing-md);
50
+ min-width: 200px;
51
+ max-width: 400px;
52
+ }
53
+ `);
54
+ }
55
+ }
56
+
57
+ constructor() {
58
+ super();
59
+ RettangoliPopoverElement.initializeStyleSheet();
60
+ this.shadow = this.attachShadow({ mode: "open" });
61
+ this.shadow.adoptedStyleSheets = [RettangoliPopoverElement.styleSheet];
62
+
63
+ // Create overlay
64
+ this._popoverOverlay = document.createElement('div');
65
+ this._popoverOverlay.className = 'popover-overlay';
66
+ this.shadow.appendChild(this._popoverOverlay);
67
+
68
+ // Handle overlay clicks to close popover
69
+ this._popoverOverlay.addEventListener('click', () => {
70
+ this.dispatchEvent(new CustomEvent('close', {
71
+ detail: {}
72
+ }));
73
+ });
74
+
75
+ // Handle right-click on overlay to close popover
76
+ this._popoverOverlay.addEventListener('contextmenu', (e) => {
77
+ e.preventDefault();
78
+ this.dispatchEvent(new CustomEvent('close', {
79
+ detail: {}
80
+ }));
81
+ });
82
+
83
+ // Create popover container
84
+ this._popoverContainer = document.createElement('div');
85
+ this._popoverContainer.className = 'popover-container';
86
+ this.shadow.appendChild(this._popoverContainer);
87
+
88
+ // Store reference for content slot
89
+ this._slotElement = null;
90
+
91
+ // Track if we're open
92
+ this._isOpen = false;
93
+
94
+ // Bind event handlers
95
+ this._handleEscKey = this._handleEscKey.bind(this);
96
+ }
97
+
98
+ static get observedAttributes() {
99
+ return ["open", "x", "y", "placement"];
100
+ }
101
+
102
+ connectedCallback() {
103
+ // Check initial open attribute
104
+ if (this.hasAttribute('open')) {
105
+ this._show();
106
+ }
107
+ }
108
+
109
+ disconnectedCallback() {
110
+ // Clean up event listeners
111
+ this._removeGlobalListeners();
112
+ }
113
+
114
+ attributeChangedCallback(name, oldValue, newValue) {
115
+ if (name === 'open') {
116
+ if (newValue !== null && !this._isOpen) {
117
+ this._show();
118
+ } else if (newValue === null && this._isOpen) {
119
+ this._hide();
120
+ }
121
+ } else if ((name === 'x' || name === 'y' || name === 'placement') && this._isOpen) {
122
+ this._updatePosition();
123
+ }
124
+ }
125
+
126
+ _show() {
127
+ if (!this._isOpen) {
128
+ // Create and append slot for content only if it doesn't exist
129
+ if (!this._slotElement) {
130
+ this._slotElement = document.createElement('slot');
131
+ this._slotElement.setAttribute('name', 'content');
132
+ this._popoverContainer.appendChild(this._slotElement);
133
+ }
134
+
135
+ this._isOpen = true;
136
+ this._updatePosition();
137
+ this._addGlobalListeners();
138
+ }
139
+ }
140
+
141
+ _hide() {
142
+ if (this._isOpen) {
143
+ this._isOpen = false;
144
+
145
+ // Remove slot to unmount content
146
+ if (this._slotElement) {
147
+ this._popoverContainer.removeChild(this._slotElement);
148
+ this._slotElement = null;
149
+ }
150
+
151
+ this._removeGlobalListeners();
152
+ }
153
+ }
154
+
155
+ _updatePosition() {
156
+ const x = parseFloat(this.getAttribute('x') || '0');
157
+ const y = parseFloat(this.getAttribute('y') || '0');
158
+ const placement = this.getAttribute('placement') || 'bottom-start';
159
+
160
+ // Remove positioned attribute to hide during repositioning
161
+ this.removeAttribute('positioned');
162
+
163
+ // Calculate position based on placement
164
+ // We'll position after the popover is rendered to get its dimensions
165
+ requestAnimationFrame(() => {
166
+ const rect = this._popoverContainer.getBoundingClientRect();
167
+ const { left, top } = this._calculatePosition(x, y, rect.width, rect.height, placement);
168
+
169
+ // Set position first
170
+ this._popoverContainer.style.left = `${left}px`;
171
+ this._popoverContainer.style.top = `${top}px`;
172
+
173
+ // Then make visible in next frame to prevent flicker
174
+ requestAnimationFrame(() => {
175
+ this.setAttribute('positioned', '');
176
+ });
177
+ });
178
+ }
179
+
180
+ _calculatePosition(x, y, width, height, placement) {
181
+ const offset = 8; // Small offset from the cursor
182
+ let left = x;
183
+ let top = y;
184
+
185
+ switch (placement) {
186
+ case 'top':
187
+ left = x - width / 2;
188
+ top = y - height - offset;
189
+ break;
190
+ case 'top-start':
191
+ left = x;
192
+ top = y - height - offset;
193
+ break;
194
+ case 'top-end':
195
+ left = x - width;
196
+ top = y - height - offset;
197
+ break;
198
+ case 'right':
199
+ left = x + offset;
200
+ top = y - height / 2;
201
+ break;
202
+ case 'right-start':
203
+ left = x + offset;
204
+ top = y;
205
+ break;
206
+ case 'right-end':
207
+ left = x + offset;
208
+ top = y - height;
209
+ break;
210
+ case 'bottom':
211
+ left = x - width / 2;
212
+ top = y + offset;
213
+ break;
214
+ case 'bottom-start':
215
+ left = x;
216
+ top = y + offset;
217
+ break;
218
+ case 'bottom-end':
219
+ left = x - width;
220
+ top = y + offset;
221
+ break;
222
+ case 'left':
223
+ left = x - width - offset;
224
+ top = y - height / 2;
225
+ break;
226
+ case 'left-start':
227
+ left = x - width - offset;
228
+ top = y;
229
+ break;
230
+ case 'left-end':
231
+ left = x - width - offset;
232
+ top = y - height;
233
+ break;
234
+ }
235
+
236
+ // Ensure popover stays within viewport
237
+ const padding = 8;
238
+ left = Math.max(padding, Math.min(left, window.innerWidth - width - padding));
239
+ top = Math.max(padding, Math.min(top, window.innerHeight - height - padding));
240
+
241
+ return { left, top };
242
+ }
243
+
244
+ _addGlobalListeners() {
245
+ // Use setTimeout to avoid immediate triggering
246
+ setTimeout(() => {
247
+ document.addEventListener('keydown', this._handleEscKey);
248
+ }, 0);
249
+ }
250
+
251
+ _removeGlobalListeners() {
252
+ document.removeEventListener('keydown', this._handleEscKey);
253
+ }
254
+
255
+
256
+ _handleEscKey(e) {
257
+ if (e.key === 'Escape') {
258
+ this.dispatchEvent(new CustomEvent('close', {
259
+ detail: {}
260
+ }));
261
+ }
262
+ }
263
+
264
+ // Expose popover container for advanced usage
265
+ get popover() {
266
+ return this._popoverContainer;
267
+ }
268
+ }
269
+
270
+ // Export factory function to maintain API compatibility
271
+ export default ({ render, html }) => {
272
+ // Note: render and html parameters are accepted but not used
273
+ // This maintains backward compatibility with existing code
274
+ return RettangoliPopoverElement;
275
+ };
@@ -1,5 +1,5 @@
1
- import {
2
- css,
1
+ import {
2
+ css,
3
3
  dimensionWithUnit,
4
4
  convertObjectToCssString,
5
5
  styleMapKeys,
@@ -22,7 +22,6 @@ class RettangoliSliderElement extends HTMLElement {
22
22
  input[type="range"] {
23
23
  -webkit-appearance: none;
24
24
  appearance: none;
25
- width: 200px;
26
25
  height: 8px;
27
26
  background: var(--muted);
28
27
  border-radius: var(--border-radius-full);
@@ -79,7 +78,7 @@ class RettangoliSliderElement extends HTMLElement {
79
78
  RettangoliSliderElement.initializeStyleSheet();
80
79
  this.shadow = this.attachShadow({ mode: "closed" });
81
80
  this.shadow.adoptedStyleSheets = [RettangoliSliderElement.styleSheet];
82
-
81
+
83
82
  // Initialize style tracking properties
84
83
  this._styles = {
85
84
  default: {},
@@ -89,12 +88,12 @@ class RettangoliSliderElement extends HTMLElement {
89
88
  xl: {},
90
89
  };
91
90
  this._lastStyleString = "";
92
-
91
+
93
92
  // Create initial DOM structure
94
93
  this._inputElement = document.createElement('input');
95
94
  this._inputElement.type = 'range';
96
95
  this._styleElement = document.createElement('style');
97
-
96
+
98
97
  this.shadow.appendChild(this._styleElement);
99
98
  this.shadow.appendChild(this._inputElement);
100
99
 
@@ -105,7 +104,7 @@ class RettangoliSliderElement extends HTMLElement {
105
104
 
106
105
  static get observedAttributes() {
107
106
  return [
108
- "key",
107
+ "key",
109
108
  "value",
110
109
  "min",
111
110
  "max",
@@ -248,7 +247,7 @@ class RettangoliSliderElement extends HTMLElement {
248
247
  } else {
249
248
  this._inputElement.step = "1";
250
249
  }
251
-
250
+
252
251
  if (isDisabled) {
253
252
  this._inputElement.setAttribute("disabled", "");
254
253
  } else {
@@ -266,4 +265,4 @@ export default ({ render, html }) => {
266
265
  // Note: render and html parameters are accepted but not used
267
266
  // This maintains backward compatibility with existing code
268
267
  return RettangoliSliderElement;
269
- };
268
+ };
@@ -100,6 +100,7 @@ const styles = {
100
100
  mu: "--muted",
101
101
  ac: "--accent",
102
102
  bo: "--border",
103
+ tr: "transparent",
103
104
  },
104
105
  br: {
105
106
  xs: "--border-radius-xs",
@@ -1,5 +0,0 @@
1
-
2
- export const handleClickDialogueOverlay = (e, deps) => {
3
- const { dispatchEvent } = deps;
4
- dispatchEvent(new CustomEvent('close-dialogue'));
5
- }
@@ -1,25 +0,0 @@
1
- export const INITIAL_STATE = Object.freeze({
2
- //
3
- });
4
-
5
- export const toViewData = ({ state, props }) => {
6
- return {
7
- isOpen: props.isOpen,
8
- w: props.w || 600,
9
- position: {
10
- x: 0,
11
- y: 0
12
- }
13
- };
14
- }
15
-
16
- export const selectState = ({ state }) => {
17
- return state;
18
- }
19
-
20
- export const setState = (state) => {
21
- // do doSomething
22
- }
23
-
24
-
25
-
@@ -1,44 +0,0 @@
1
- elementName: rtgl-dialog
2
-
3
- viewDataSchema:
4
- type: object
5
-
6
- propsSchema:
7
- type: object
8
- properties:
9
- isOpen:
10
- type: boolean
11
- w:
12
- type: string
13
-
14
- refs:
15
- dialog-overlay:
16
- eventListeners:
17
- click:
18
- handler: handleClickDialogueOverlay
19
-
20
- events:
21
- close-dialogue:
22
- type: object
23
- properties: {}
24
-
25
- styles:
26
- # '@keyframes dialog-in':
27
- # from:
28
- # opacity: 0
29
- # transform: scale(0.95)
30
- # to:
31
- # opacity: 1
32
- # transform: scale(1)
33
-
34
- # '#dialog-container':
35
- # animation: dialog-in 150ms cubic-bezier(0.16, 1, 0.3, 1)
36
- # transform-origin: top
37
-
38
- template:
39
- - $if isOpen:
40
- - rtgl-view pos=fix cor=full ah=c:
41
- - 'rtgl-view#dialog-overlay pos=fix cor=full ah=c av=c bgc=bg op=0.5':
42
- - rtgl-view h=10vh:
43
- - rtgl-view#dialog-container z=100 bw=xs p=lg bgc=bg w=${w} br=sm:
44
- - slot name=content:
@@ -1,5 +0,0 @@
1
-
2
- export const handleClickOverlay = (e, deps) => {
3
- const { dispatchEvent } = deps;
4
- dispatchEvent(new CustomEvent('click-overlay'));
5
- }
@@ -1,12 +0,0 @@
1
- export const INITIAL_STATE = Object.freeze({});
2
-
3
- export const toViewData = ({ state, props }) => {
4
- return {
5
- isOpen: props.isOpen,
6
- position: props.position,
7
- };
8
- }
9
-
10
- export const selectState = ({ state }) => {
11
- return state;
12
- }
@@ -1,57 +0,0 @@
1
- elementName: rtgl-popover
2
-
3
- viewDataSchema:
4
- type: object
5
- properties:
6
- isOpen:
7
- type: boolean
8
- position:
9
- type: object
10
- properties:
11
- x:
12
- type: number
13
- y:
14
- type: number
15
- placement:
16
- type: string
17
-
18
- propsSchema:
19
- type: object
20
- properties:
21
- placement:
22
- type: string
23
- default: bottom
24
- isOpen:
25
- type: boolean
26
- position:
27
- type: object
28
- properties:
29
- x:
30
- type: number
31
- y:
32
- type: number
33
-
34
- refs:
35
- popoverOverlay:
36
- eventListeners:
37
- click:
38
- handler: handleClickOverlay
39
-
40
- styles:
41
- '@keyframes popover-in':
42
- from:
43
- opacity: 0
44
- transform: scale(0.95)
45
- to:
46
- opacity: 1
47
- transform: scale(1)
48
-
49
- '#popoverContainer':
50
- animation: popover-in 150ms cubic-bezier(0.16, 1, 0.3, 1)
51
- transform-origin: top
52
-
53
- template:
54
- - $if isOpen:
55
- - rtgl-view#popoverOverlay pos=fix cor=full:
56
- - 'rtgl-view#popoverContainer pos=fix style="left: ${position.x}px; top: ${position.y}px;" id=floatingElement bw=xs p=md bgc=mu':
57
- - slot name=content: