@rettangoli/ui 0.1.2-rc28 → 0.1.2-rc29

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/ui",
3
- "version": "0.1.2-rc28",
3
+ "version": "0.1.2-rc29",
4
4
  "description": "A UI component library for building web interfaces.",
5
5
  "main": "dist/rettangoli-esm.min.js",
6
6
  "type": "module",
@@ -200,3 +200,28 @@ export const handleSelectAddOption = (e, deps) => {
200
200
  }),
201
201
  );
202
202
  };
203
+
204
+ export const handleTooltipMouseEnter = (e, deps) => {
205
+ const { store, render, props } = deps;
206
+ const fieldName = e.currentTarget.id.replace('tooltip-icon-', '');
207
+
208
+ // Find the field with matching name to get tooltip content
209
+ const form = props.form;
210
+ const field = form.fields.find(f => f.name === fieldName);
211
+
212
+ if (field && field.tooltip) {
213
+ const rect = e.currentTarget.getBoundingClientRect();
214
+ store.showTooltip({
215
+ x: rect.left + rect.width / 2,
216
+ y: rect.top - 8,
217
+ content: field.tooltip.content
218
+ });
219
+ render();
220
+ }
221
+ };
222
+
223
+ export const handleTooltipMouseLeave = (e, deps) => {
224
+ const { store, render } = deps;
225
+ store.hideTooltip();
226
+ render();
227
+ };
@@ -26,6 +26,12 @@ function pick(obj, keys) {
26
26
 
27
27
  export const INITIAL_STATE = Object.freeze({
28
28
  formValues: {},
29
+ tooltipState: {
30
+ open: false,
31
+ x: 0,
32
+ y: 0,
33
+ content: ''
34
+ },
29
35
  });
30
36
 
31
37
  // Lodash-like utility functions for nested property access
@@ -140,6 +146,7 @@ export const toViewData = ({ state, props, attrs }) => {
140
146
  buttons: [],
141
147
  },
142
148
  formValues: state.formValues,
149
+ tooltipState: state.tooltipState,
143
150
  };
144
151
  };
145
152
 
@@ -174,3 +181,19 @@ export const setFormFieldValue = (state, { name, value, props }) => {
174
181
  );
175
182
  state.formValues = formValues;
176
183
  };
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
+ };
@@ -33,6 +33,11 @@ propsSchema:
33
33
  const: inputText
34
34
  placeholder:
35
35
  type: string
36
+ tooltip:
37
+ type: object
38
+ properties:
39
+ content:
40
+ type: string
36
41
  required:
37
42
  - name
38
43
  - label
@@ -69,6 +74,11 @@ propsSchema:
69
74
  required:
70
75
  - label
71
76
  - value
77
+ tooltip:
78
+ type: object
79
+ properties:
80
+ content:
81
+ type: string
72
82
  required:
73
83
  - name
74
84
  - label
@@ -87,6 +97,11 @@ propsSchema:
87
97
  const: colorPicker
88
98
  value:
89
99
  type: string
100
+ tooltip:
101
+ type: object
102
+ properties:
103
+ content:
104
+ type: string
90
105
  required:
91
106
  - name
92
107
  - label
@@ -110,6 +125,11 @@ propsSchema:
110
125
  type: number
111
126
  value:
112
127
  type: number
128
+ tooltip:
129
+ type: object
130
+ properties:
131
+ content:
132
+ type: string
113
133
  required:
114
134
  - name
115
135
  - label
@@ -133,6 +153,11 @@ propsSchema:
133
153
  type: number
134
154
  value:
135
155
  type: number
156
+ tooltip:
157
+ type: object
158
+ properties:
159
+ content:
160
+ type: string
136
161
  required:
137
162
  - name
138
163
  - label
@@ -154,6 +179,11 @@ propsSchema:
154
179
  type: number
155
180
  placeholder:
156
181
  type: string
182
+ tooltip:
183
+ type: object
184
+ properties:
185
+ content:
186
+ type: string
157
187
  required:
158
188
  - name
159
189
  - label
@@ -179,6 +209,33 @@ propsSchema:
179
209
  type: object
180
210
  waveformData:
181
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
182
239
  required:
183
240
  - name
184
241
  - label
@@ -205,6 +262,12 @@ refs:
205
262
  eventListeners:
206
263
  click:
207
264
  handler: handleActionClick
265
+ tooltip-icon-*:
266
+ eventListeners:
267
+ mouseenter:
268
+ handler: handleTooltipMouseEnter
269
+ mouseleave:
270
+ handler: handleTooltipMouseLeave
208
271
  input-*:
209
272
  eventListeners:
210
273
  input-change:
@@ -258,7 +321,10 @@ template:
258
321
  - $for field, i in fields:
259
322
  - rtgl-view g=md w=f:
260
323
  - rtgl-view g=sm:
261
- - rtgl-text: ${field.label}
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:
262
328
  - rtgl-text s=sm c=mu-fg: ${field.description}
263
329
  - $if field.inputType == "read-only-text":
264
330
  - rtgl-text s=sm: ${field.defaultValue}
@@ -290,3 +356,4 @@ template:
290
356
  - rtgl-view d=h ah=e g=sm w=f:
291
357
  - $for button, i in actions.buttons:
292
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}":
File without changes
@@ -0,0 +1,12 @@
1
+ export const INITIAL_STATE = Object.freeze({
2
+ });
3
+
4
+ export const toViewData = ({ 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
+
@@ -296,6 +296,16 @@ class RettangoliButtonElement extends HTMLElement {
296
296
  this._buttonElement.style.maxWidth = "";
297
297
  }
298
298
  }
299
+
300
+ // Public method to get the actual button's bounding rect
301
+ // This is needed because the host element has display: contents
302
+ getBoundingClientRect() {
303
+ if (this._buttonElement) {
304
+ return this._buttonElement.getBoundingClientRect();
305
+ }
306
+ // Fallback to host element
307
+ return super.getBoundingClientRect();
308
+ }
299
309
  }
300
310
 
301
311
  // Export factory function to maintain API compatibility
@@ -28,7 +28,7 @@ class RettangoliPopoverElement extends HTMLElement {
28
28
  outline: none;
29
29
  }
30
30
 
31
- :host([open]) .popover-overlay {
31
+ :host([open]:not([no-overlay])) .popover-overlay {
32
32
  display: block;
33
33
  }
34
34
 
@@ -36,6 +36,11 @@ class RettangoliPopoverElement extends HTMLElement {
36
36
  display: block;
37
37
  visibility: hidden;
38
38
  }
39
+
40
+ /* For no-overlay mode, make the container non-interactive */
41
+ :host([no-overlay]) .popover-container {
42
+ pointer-events: none;
43
+ }
39
44
 
40
45
  :host([open][positioned]) .popover-container {
41
46
  visibility: visible;
@@ -96,7 +101,7 @@ class RettangoliPopoverElement extends HTMLElement {
96
101
  }
97
102
 
98
103
  static get observedAttributes() {
99
- return ["open", "x", "y", "placement"];
104
+ return ["open", "x", "y", "placement", "no-overlay"];
100
105
  }
101
106
 
102
107
  connectedCallback() {