rettangoli-ui 0.1.0-rc2 → 0.1.0-rc4

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/README.md +16 -27
  2. package/dist/rettangoli-iife-layout.min.js +118 -45
  3. package/dist/rettangoli-iife-ui.min.js +86 -65
  4. package/package.json +11 -4
  5. package/src/common/BaseElement.js +182 -0
  6. package/src/common.js +190 -0
  7. package/src/components/dialog/dialog.handlers.js +5 -0
  8. package/src/components/dialog/dialog.store.js +24 -0
  9. package/src/components/dialog/dialog.view.yaml +41 -0
  10. package/src/components/dropdownMenu/dropdownMenu.handlers.js +5 -0
  11. package/src/components/dropdownMenu/dropdownMenu.store.js +25 -0
  12. package/src/components/dropdownMenu/dropdownMenu.view.yaml +52 -0
  13. package/src/components/form/form.handlers.js +30 -0
  14. package/src/components/form/form.store.js +45 -0
  15. package/src/components/form/form.view.yaml +47 -0
  16. package/src/components/navbar/navbar.examples.yaml +86 -0
  17. package/src/components/navbar/navbar.handlers.js +10 -0
  18. package/src/components/navbar/navbar.store.js +46 -0
  19. package/src/components/navbar/navbar.view.yaml +74 -0
  20. package/src/components/pageOutline/pageOutline.handlers.js +69 -0
  21. package/src/components/pageOutline/pageOutline.store.js +40 -0
  22. package/src/components/pageOutline/pageOutline.view.yaml +34 -0
  23. package/src/components/popover/popover.handlers.js +5 -0
  24. package/src/components/popover/popover.store.js +12 -0
  25. package/src/components/popover/popover.view.yaml +57 -0
  26. package/src/components/select/select.handlers.js +46 -0
  27. package/src/components/select/select.store.js +65 -0
  28. package/src/components/select/select.view.yaml +50 -0
  29. package/src/components/sidebar/sidebar.handlers.js +36 -0
  30. package/src/components/sidebar/sidebar.store.js +139 -0
  31. package/src/components/sidebar/sidebar.view.yaml +190 -0
  32. package/src/entry-iife-layout.js +15 -0
  33. package/src/entry-iife-ui.js +18 -0
  34. package/src/index.js +17 -0
  35. package/src/lib/uhtml.js +9 -0
  36. package/src/primitives/button.js +306 -0
  37. package/src/primitives/image.js +234 -0
  38. package/src/primitives/input.js +208 -0
  39. package/src/primitives/svg.js +95 -0
  40. package/src/primitives/text.js +141 -0
  41. package/src/primitives/textarea.js +103 -0
  42. package/src/primitives/view.js +217 -0
  43. package/src/setup.js +16 -0
  44. package/src/styles/anchorStyles.js +13 -0
  45. package/src/styles/buttonMarginStyles.js +84 -0
  46. package/src/styles/cursorStyles.js +12 -0
  47. package/src/styles/flexChildStyles.js +43 -0
  48. package/src/styles/flexDirectionStyles.js +74 -0
  49. package/src/styles/marginStyles.js +13 -0
  50. package/src/styles/paddingSvgStyles.js +120 -0
  51. package/src/styles/scrollStyles.js +22 -0
  52. package/src/styles/textColorStyles.js +14 -0
  53. package/src/styles/textStyles.js +62 -0
  54. package/src/styles/viewStyles.js +119 -0
@@ -0,0 +1,306 @@
1
+ import { css, dimensionWithUnit } from "../common.js";
2
+ import flexChildStyles from "../styles/flexChildStyles.js";
3
+ import buttonMarginStyles from "../styles/buttonMarginStyles.js";
4
+ import anchorStyles from "../styles/anchorStyles.js";
5
+
6
+ // Internal implementation without uhtml
7
+ class RettangoliButtonElement extends HTMLElement {
8
+ static styleSheet = null;
9
+
10
+ static initializeStyleSheet() {
11
+ if (!RettangoliButtonElement.styleSheet) {
12
+ RettangoliButtonElement.styleSheet = new CSSStyleSheet();
13
+ RettangoliButtonElement.styleSheet.replaceSync(css`
14
+ :host {
15
+ display: contents;
16
+ }
17
+ slot {
18
+ display: contents;
19
+ }
20
+
21
+ button {
22
+ display: flex;
23
+ flex-direction: row;
24
+ align-items: center;
25
+ justify-content: center;
26
+ gap: var(--spacing-lg);
27
+ border-width: 0px;
28
+ border-style: solid;
29
+ border-color: var(--border);
30
+ padding: 0px;
31
+ height: 32px;
32
+ padding-left: 16px;
33
+ padding-right: 16px;
34
+ border-radius: 4px;
35
+
36
+ font-size: var(--sm-font-size);
37
+ font-weight: var(--sm-font-weight);
38
+ line-height: var(--sm-line-height);
39
+ letter-spacing: var(--sm-letter-spacing);
40
+
41
+ background-color: var(--primary);
42
+ color: var(--primary-foreground);
43
+ }
44
+
45
+ button:hover {
46
+ cursor: pointer;
47
+ background-color: color-mix(
48
+ in srgb,
49
+ var(--primary) 85%,
50
+ white 15%
51
+ );
52
+ }
53
+
54
+ button:disabled {
55
+ cursor: not-allowed;
56
+ }
57
+
58
+ button:active {
59
+ cursor: pointer;
60
+ background-color: color-mix(
61
+ in srgb,
62
+ var(--primary) 80%,
63
+ white 20%
64
+ );
65
+ }
66
+
67
+ :host([v="pr"]) button:hover {
68
+ background-color: color-mix(
69
+ in srgb,
70
+ var(--primary) 85%,
71
+ white 15%
72
+ );
73
+ }
74
+
75
+ :host([v="pr"]) button:active {
76
+ background-color: color-mix(
77
+ in srgb,
78
+ var(--primary) 80%,
79
+ white 20%
80
+ );
81
+ }
82
+
83
+ :host([v="se"]) button:hover {
84
+ background-color: color-mix(
85
+ in srgb,
86
+ var(--secondary) 85%,
87
+ white 15%
88
+ );
89
+ }
90
+
91
+ :host([v="se"]) button:active {
92
+ background-color: color-mix(
93
+ in srgb,
94
+ var(--secondary) 80%,
95
+ white 20%
96
+ );
97
+ }
98
+
99
+ :host([v="de"]) button:hover {
100
+ background-color: color-mix(
101
+ in srgb,
102
+ var(--destructive) 85%,
103
+ white 15%
104
+ );
105
+ }
106
+
107
+ :host([v="de"]) button:active {
108
+ background-color: color-mix(
109
+ in srgb,
110
+ var(--destructive) 80%,
111
+ white 20%
112
+ );
113
+ }
114
+
115
+ :host([v="ol"]) button:hover {
116
+ background-color: var(--accent);
117
+ }
118
+
119
+ :host([v="gh"]) button:hover {
120
+ background-color: var(--accent);
121
+ }
122
+
123
+ :host([v="lk"]) button:hover {
124
+ text-decoration: underline;
125
+ }
126
+
127
+ /* Square button styles */
128
+ :host([sq]) button {
129
+ width: 32px;
130
+ height: 32px;
131
+ padding: 0;
132
+ gap: 0;
133
+ }
134
+
135
+ :host([sq][s="sm"]) button {
136
+ width: 24px;
137
+ height: 24px;
138
+ padding: 0;
139
+ gap: 0;
140
+ }
141
+
142
+ :host([sq][s="lg"]) button {
143
+ width: 40px;
144
+ height: 40px;
145
+ padding: 0;
146
+ gap: 0;
147
+ }
148
+
149
+ ${anchorStyles}
150
+
151
+ a {
152
+ display: contents;
153
+ }
154
+
155
+ ${buttonMarginStyles}
156
+ ${flexChildStyles}
157
+ `);
158
+ }
159
+ }
160
+
161
+ constructor() {
162
+ super();
163
+ RettangoliButtonElement.initializeStyleSheet();
164
+ this.shadow = this.attachShadow({ mode: "closed" });
165
+ this.shadow.adoptedStyleSheets = [RettangoliButtonElement.styleSheet];
166
+
167
+ // Create initial DOM structure
168
+ this._containerElement = null;
169
+ this._buttonElement = document.createElement('button');
170
+ this._slotElement = document.createElement('slot');
171
+ this._iconElement = null;
172
+
173
+ this._buttonElement.appendChild(this._slotElement);
174
+ }
175
+
176
+ static get observedAttributes() {
177
+ return ["key", "href", "target", "w", "t", "icon", "disabled", "v", "s", "sq", "ip"];
178
+ }
179
+
180
+ connectedCallback() {
181
+ this._updateButton();
182
+ }
183
+
184
+ attributeChangedCallback(name, oldValue, newValue) {
185
+ this._updateButton();
186
+ }
187
+
188
+ _updateButton() {
189
+ // Clear shadow DOM
190
+ this.shadow.innerHTML = '';
191
+
192
+ // Update icon
193
+ this._updateIcon();
194
+
195
+ // Update width styling (skip for square buttons)
196
+ if (!this.hasAttribute('sq')) {
197
+ this._updateWidth();
198
+ }
199
+
200
+ // Update disabled state
201
+ const isDisabled = this.hasAttribute('disabled');
202
+ if (isDisabled) {
203
+ this._buttonElement.setAttribute('disabled', '');
204
+ } else {
205
+ this._buttonElement.removeAttribute('disabled');
206
+ }
207
+
208
+ // Handle href (link) vs button
209
+ const href = this.getAttribute("href");
210
+ if (href) {
211
+ // Create anchor wrapper
212
+ const anchorElement = document.createElement('a');
213
+ anchorElement.setAttribute('href', href);
214
+
215
+ const target = this.getAttribute("target");
216
+ if (target) {
217
+ anchorElement.setAttribute('target', target);
218
+ }
219
+
220
+ anchorElement.appendChild(this._buttonElement);
221
+ this.shadow.appendChild(anchorElement);
222
+ this._containerElement = anchorElement;
223
+ } else {
224
+ // Direct button
225
+ this.shadow.appendChild(this._buttonElement);
226
+ this._containerElement = this._buttonElement;
227
+ }
228
+ }
229
+
230
+ _updateIcon() {
231
+ // Remove existing icon if any
232
+ if (this._iconElement) {
233
+ this._iconElement.remove();
234
+ this._iconElement = null;
235
+ }
236
+
237
+ const icon = this.getAttribute("icon");
238
+ if (icon) {
239
+ const colorMap = {
240
+ pr: 'pr-fg',
241
+ se: 'ac-fg',
242
+ de: 'pr-fg',
243
+ ol: 'ac-fg',
244
+ gh: 'ac-fg',
245
+ lk: 'ac-fg'
246
+ };
247
+ const sizeMap = {
248
+ sm: 14,
249
+ md: 18,
250
+ lg: 22
251
+ };
252
+ const color = colorMap[this.getAttribute("v")] || 'pr-fg';
253
+
254
+ // For square buttons, use button size (s attribute), otherwise use icon size (t attribute)
255
+ let size = 18; // default
256
+ if (this.hasAttribute('sq')) {
257
+ const buttonSizeMap = {
258
+ sm: 14,
259
+ lg: 22
260
+ };
261
+ const buttonSize = this.getAttribute("s");
262
+ size = buttonSizeMap[buttonSize] || 18;
263
+ } else {
264
+ size = sizeMap[this.getAttribute("t")] || 18;
265
+ }
266
+
267
+ this._iconElement = document.createElement('rtgl-svg');
268
+ this._iconElement.setAttribute('svg', icon);
269
+ this._iconElement.setAttribute('c', color);
270
+ this._iconElement.setAttribute('wh', size.toString());
271
+
272
+ // Insert icon based on position (default is right, 's' means start/left)
273
+ const iconPosition = this.getAttribute("ip");
274
+ if (iconPosition === 's') {
275
+ // Insert icon before slot (left position)
276
+ this._buttonElement.insertBefore(this._iconElement, this._slotElement);
277
+ } else {
278
+ // Insert icon after slot (right position - default)
279
+ this._buttonElement.appendChild(this._iconElement);
280
+ }
281
+ }
282
+ }
283
+
284
+ _updateWidth() {
285
+ const width = dimensionWithUnit(this.getAttribute("w"));
286
+
287
+ if (width === "f") {
288
+ this._buttonElement.style.width = "var(--width-stretch)";
289
+ } else if (width !== undefined && width !== null) {
290
+ this._buttonElement.style.width = width;
291
+ this._buttonElement.style.minWidth = width;
292
+ this._buttonElement.style.maxWidth = width;
293
+ } else {
294
+ this._buttonElement.style.width = "";
295
+ this._buttonElement.style.minWidth = "";
296
+ this._buttonElement.style.maxWidth = "";
297
+ }
298
+ }
299
+ }
300
+
301
+ // Export factory function to maintain API compatibility
302
+ export default ({ render, html }) => {
303
+ // Note: render and html parameters are accepted but not used
304
+ // This maintains backward compatibility with existing code
305
+ return RettangoliButtonElement;
306
+ };
@@ -0,0 +1,234 @@
1
+ import {
2
+ css,
3
+ dimensionWithUnit,
4
+ convertObjectToCssString,
5
+ styleMapKeys,
6
+ permutateBreakpoints
7
+ } from "../common.js";
8
+ import cursorStyles from "../styles/cursorStyles.js";
9
+ import marginStyles from "../styles/marginStyles.js";
10
+ import viewStyles from "../styles/viewStyles.js";
11
+ import anchorStyles from "../styles/anchorStyles.js";
12
+
13
+ // Internal implementation without uhtml
14
+ class RettangoliImageElement extends HTMLElement {
15
+ static styleSheet = null;
16
+
17
+ static initializeStyleSheet() {
18
+ if (!RettangoliImageElement.styleSheet) {
19
+ RettangoliImageElement.styleSheet = new CSSStyleSheet();
20
+ RettangoliImageElement.styleSheet.replaceSync(css`
21
+ :host {
22
+ border-style: solid;
23
+ box-sizing: border-box;
24
+ overflow: hidden;
25
+ border-width: 0;
26
+ }
27
+ slot {
28
+ display: contents;
29
+ }
30
+ :host([of="con"]) img {
31
+ object-fit: contain;
32
+ }
33
+ :host([of="cov"]) img {
34
+ object-fit: cover;
35
+ }
36
+ :host([of="none"]) img {
37
+ object-fit: none;
38
+ }
39
+ img {
40
+ height: 100%;
41
+ width: 100%;
42
+ }
43
+
44
+ ${anchorStyles}
45
+
46
+ a {
47
+ display: block;
48
+ height: 100%;
49
+ width: 100%;
50
+ }
51
+
52
+ :host([href]) {
53
+ cursor: pointer;
54
+ }
55
+
56
+ ${viewStyles}
57
+ ${marginStyles}
58
+ ${cursorStyles}
59
+ `);
60
+ }
61
+ }
62
+
63
+ constructor() {
64
+ super();
65
+ RettangoliImageElement.initializeStyleSheet();
66
+ this.shadow = this.attachShadow({ mode: "closed" });
67
+ this.shadow.adoptedStyleSheets = [RettangoliImageElement.styleSheet];
68
+
69
+ // Create initial DOM structure
70
+ this._styleElement = document.createElement('style');
71
+ this._imgElement = document.createElement('img');
72
+ this._linkElement = null;
73
+
74
+ this.shadow.appendChild(this._styleElement);
75
+ this._updateDOM();
76
+ }
77
+
78
+ static get observedAttributes() {
79
+ return permutateBreakpoints([...styleMapKeys, "key", "src", "href", "target", "wh", "w", "h", "hidden", "height", "width"]);
80
+ }
81
+
82
+ _styles = {
83
+ default: {},
84
+ sm: {},
85
+ md: {},
86
+ lg: {},
87
+ xl: {},
88
+ };
89
+
90
+ _lastStyleString = "";
91
+
92
+ _updateDOM() {
93
+ const href = this.getAttribute("href");
94
+ const target = this.getAttribute("target");
95
+
96
+ if (href) {
97
+ if (!this._linkElement) {
98
+ // Create link wrapper
99
+ this._linkElement = document.createElement("a");
100
+ }
101
+
102
+ // Update link attributes
103
+ this._linkElement.href = href;
104
+ if (target) {
105
+ this._linkElement.target = target;
106
+ } else {
107
+ this._linkElement.removeAttribute("target");
108
+ }
109
+
110
+ // Wrap image in link
111
+ this._linkElement.appendChild(this._imgElement);
112
+
113
+ // Ensure link is in shadow DOM
114
+ if (this._linkElement.parentNode !== this.shadow) {
115
+ this.shadow.appendChild(this._linkElement);
116
+ }
117
+ } else if (this._linkElement) {
118
+ // Remove link wrapper
119
+ if (this._imgElement.parentNode === this._linkElement) {
120
+ this.shadow.appendChild(this._imgElement);
121
+ }
122
+ if (this._linkElement.parentNode === this.shadow) {
123
+ this.shadow.removeChild(this._linkElement);
124
+ }
125
+ this._linkElement = null;
126
+ } else {
127
+ // Ensure image is in shadow DOM
128
+ if (this._imgElement.parentNode !== this.shadow) {
129
+ this.shadow.appendChild(this._imgElement);
130
+ }
131
+ }
132
+ }
133
+
134
+ attributeChangedCallback(name, oldValue, newValue) {
135
+ // Handle href and target changes
136
+ if (name === "href" || name === "target") {
137
+ this._updateDOM();
138
+ return;
139
+ }
140
+ // Reset styles for fresh calculation
141
+ this._styles = {
142
+ default: {},
143
+ sm: {},
144
+ md: {},
145
+ lg: {},
146
+ xl: {},
147
+ };
148
+
149
+ ["default", "sm", "md", "lg", "xl"].forEach((size) => {
150
+ const addSizePrefix = (tag) => {
151
+ return `${size === "default" ? "" : `${size}-`}${tag}`;
152
+ };
153
+
154
+ const wh = this.getAttribute(addSizePrefix("wh"));
155
+ const width = dimensionWithUnit(
156
+ wh === null ? this.getAttribute(addSizePrefix("w")) : wh
157
+ );
158
+ const height = dimensionWithUnit(
159
+ wh === null ? this.getAttribute(addSizePrefix("h")) : wh
160
+ );
161
+ const opacity = this.getAttribute(addSizePrefix("o"));
162
+ const zIndex = this.getAttribute(addSizePrefix("z"));
163
+
164
+ if (zIndex !== null) {
165
+ this._styles[size]["z-index"] = zIndex;
166
+ }
167
+
168
+ if (opacity !== null) {
169
+ this._styles[size].opacity = opacity;
170
+ }
171
+
172
+ if (width === "f") {
173
+ this._styles[size].width = "var(--width-stretch)";
174
+ } else if (width !== undefined) {
175
+ this._styles[size].width = width;
176
+ this._styles[size]["min-width"] = width;
177
+ this._styles[size]["max-width"] = width;
178
+ }
179
+
180
+ if (height === "f") {
181
+ this._styles[size].height = "100%";
182
+ } else if (height !== undefined) {
183
+ this._styles[size].height = height;
184
+ this._styles[size]["min-height"] = height;
185
+ this._styles[size]["max-height"] = height;
186
+ }
187
+
188
+ if (this.hasAttribute(addSizePrefix("hidden"))) {
189
+ this._styles[size].display = "none !important";
190
+ }
191
+
192
+ if (this.hasAttribute(addSizePrefix("visible"))) {
193
+ this._styles[size].display = "block !important";
194
+ }
195
+ });
196
+
197
+ // Update styles only if changed
198
+ const newStyleString = convertObjectToCssString(this._styles);
199
+ if (newStyleString !== this._lastStyleString) {
200
+ this._styleElement.textContent = newStyleString;
201
+ this._lastStyleString = newStyleString;
202
+ }
203
+
204
+ // Update img attributes
205
+ this._updateImageAttributes();
206
+ }
207
+
208
+ _updateImageAttributes() {
209
+ const src = this.getAttribute("src");
210
+ const width = this.getAttribute("width");
211
+ const height = this.getAttribute("height");
212
+
213
+ if (src !== null) {
214
+ this._imgElement.setAttribute("src", src);
215
+ }
216
+ if (width !== null) {
217
+ this._imgElement.setAttribute("width", width);
218
+ }
219
+ if (height !== null) {
220
+ this._imgElement.setAttribute("height", height);
221
+ }
222
+ }
223
+
224
+ connectedCallback() {
225
+ this._updateImageAttributes();
226
+ }
227
+ }
228
+
229
+ // Export factory function to maintain API compatibility
230
+ export default ({ render, html }) => {
231
+ // Note: render and html parameters are accepted but not used
232
+ // This maintains backward compatibility with existing code
233
+ return RettangoliImageElement;
234
+ };