@rettangoli/ui 1.0.0-rc13 → 1.0.0-rc15

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 (37) hide show
  1. package/dist/rettangoli-iife-layout.min.js +81 -49
  2. package/dist/rettangoli-iife-ui.min.js +150 -49
  3. package/package.json +10 -5
  4. package/src/common/dimensions.js +85 -0
  5. package/src/common/responsive.js +72 -0
  6. package/src/common.js +6 -4
  7. package/src/components/dropdownMenu/dropdownMenu.schema.yaml +1 -1
  8. package/src/components/form/form.handlers.js +328 -152
  9. package/src/components/form/form.methods.js +205 -0
  10. package/src/components/form/form.schema.yaml +16 -271
  11. package/src/components/form/form.store.js +535 -95
  12. package/src/components/form/form.view.yaml +73 -52
  13. package/src/components/globalUi/globalUi.handlers.js +4 -4
  14. package/src/components/popoverInput/popoverInput.handlers.js +64 -50
  15. package/src/components/popoverInput/popoverInput.schema.yaml +3 -1
  16. package/src/components/popoverInput/popoverInput.store.js +9 -3
  17. package/src/components/popoverInput/popoverInput.view.yaml +4 -4
  18. package/src/components/select/select.handlers.js +15 -19
  19. package/src/components/select/select.schema.yaml +2 -0
  20. package/src/components/select/select.store.js +8 -6
  21. package/src/components/select/select.view.yaml +4 -4
  22. package/src/components/sliderInput/sliderInput.handlers.js +15 -1
  23. package/src/components/sliderInput/sliderInput.schema.yaml +3 -0
  24. package/src/components/sliderInput/sliderInput.store.js +2 -1
  25. package/src/components/sliderInput/sliderInput.view.yaml +2 -2
  26. package/src/components/tooltip/tooltip.schema.yaml +1 -1
  27. package/src/deps/createGlobalUI.js +4 -4
  28. package/src/entry-iife-layout.js +6 -0
  29. package/src/entry-iife-ui.js +8 -0
  30. package/src/index.js +8 -0
  31. package/src/primitives/checkbox.js +295 -0
  32. package/src/primitives/input-date.js +31 -0
  33. package/src/primitives/input-datetime.js +31 -0
  34. package/src/primitives/input-time.js +31 -0
  35. package/src/primitives/input.js +43 -1
  36. package/src/primitives/textarea.js +3 -0
  37. package/src/primitives/view.js +6 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/ui",
3
- "version": "1.0.0-rc13",
3
+ "version": "1.0.0-rc15",
4
4
  "description": "A UI component library for building web interfaces.",
5
5
  "main": "dist/rettangoli-esm.min.js",
6
6
  "type": "module",
@@ -27,14 +27,17 @@
27
27
  },
28
28
  "license": "MIT",
29
29
  "scripts": {
30
- "check:contracts": "rtgl fe check",
30
+ "test": "vitest run --reporter=verbose",
31
+ "test:puty": "vitest run puty.spec.js --reporter=verbose",
32
+ "check:contracts": "rtgl check --dir src/components",
33
+ "check:contracts:yahtml": "rtgl check --dir src/components",
31
34
  "copy:css": "node copy-css.js",
32
35
  "build:dev": "rtgl fe build -d && bun run esbuild-dev.js && npm run copy:css",
33
36
  "build": "rtgl fe build && bun run esbuild.js && bun run esbuild-dev.js && npm run copy:css && npm run verify:vt-bundle",
34
37
  "verify:vt-bundle": "rg -q 'customElements\\.define\\(\"rtgl-button\"' vt/static/public/main.js",
35
38
  "prepack": "npm run build",
36
39
  "vt:generate": "bun run build:dev && rtgl vt generate",
37
- "vt:docker": "bun run build:dev && bash -lc 'IMAGE=\"han4wluc/rtgl:playwright-v1.57.0-rtgl-v1.0.0-rc13\"; docker pull \"$IMAGE\" >/dev/null 2>&1 || IMAGE=\"han4wluc/rtgl:playwright-v1.57.0-rtgl-v1.0.0-rc12\"; docker run --rm --user $(id -u):$(id -g) -v \"$PWD:/app\" -w /app \"$IMAGE\" rtgl vt screenshot'",
40
+ "vt:docker": "bun run build:dev && bash -lc 'IMAGE=\"han4wluc/rtgl:playwright-v1.57.0-rtgl-v1.0.0-rc27\"; docker pull \"$IMAGE\" >/dev/null 2>&1 || IMAGE=\"han4wluc/rtgl:playwright-v1.57.0-rtgl-v1.0.0-rc26\"; docker run --rm --user $(id -u):$(id -g) -v \"$PWD:/app\" -w /app \"$IMAGE\" rtgl vt screenshot'",
38
41
  "vt:report": "bun run vt:docker && rtgl vt report",
39
42
  "vt:accept": "rtgl vt accept",
40
43
  "serve": "bunx serve .rettangoli/vt/_site"
@@ -44,7 +47,9 @@
44
47
  "looks-same": "^9.0.1",
45
48
  "pixelmatch": "^6.0.0",
46
49
  "playwright": "1.57.0",
47
- "pngjs": "^7.0.0"
50
+ "pngjs": "^7.0.0",
51
+ "puty": "^0.1.1",
52
+ "vitest": "^4.0.15"
48
53
  },
49
54
  "keywords": [
50
55
  "ui",
@@ -58,7 +63,7 @@
58
63
  "homepage": "https://github.com/yuusoft-org/rettangoli#readme",
59
64
  "dependencies": {
60
65
  "@floating-ui/dom": "^1.6.13",
61
- "@rettangoli/fe": "1.0.0-rc1",
66
+ "@rettangoli/fe": "workspace:*",
62
67
  "commander": "^13.1.0",
63
68
  "jempl": "1.0.0",
64
69
  "js-yaml": "^4.1.0",
@@ -1,32 +1,101 @@
1
1
  const FLEX_GROW_DIMENSION_REGEX = /^([1-9]|1[0-2])fg$/;
2
+ const FLEX_BASIS_DIMENSION_REGEX = /^([1-9]\d*)\/([1-9]\d*)fb$/;
2
3
 
3
4
  export const isFlexGrowDimension = (dimension) => {
4
5
  return typeof dimension === "string" && FLEX_GROW_DIMENSION_REGEX.test(dimension);
5
6
  };
6
7
 
8
+ export const parseFlexBasisDimension = (dimension) => {
9
+ if (typeof dimension !== "string") {
10
+ return null;
11
+ }
12
+
13
+ const match = dimension.match(FLEX_BASIS_DIMENSION_REGEX);
14
+ if (!match) {
15
+ return null;
16
+ }
17
+
18
+ const numerator = Number(match[1]);
19
+ const denominator = Number(match[2]);
20
+ if (!Number.isInteger(numerator) || !Number.isInteger(denominator) || denominator <= 0 || numerator > denominator) {
21
+ return null;
22
+ }
23
+
24
+ return { numerator, denominator };
25
+ };
26
+
27
+ export const isFlexBasisDimension = (dimension) => {
28
+ return parseFlexBasisDimension(dimension) !== null;
29
+ };
30
+
31
+ function toFlexBasisCss({ numerator, denominator, gapVar }) {
32
+ if (numerator === denominator) {
33
+ return "100%";
34
+ }
35
+
36
+ if (numerator === 1) {
37
+ return `calc((100% - ((${denominator} - 1) * ${gapVar})) / ${denominator})`;
38
+ }
39
+
40
+ return `calc(((100% - ((${denominator} - 1) * ${gapVar})) * ${numerator}) / ${denominator})`;
41
+ }
42
+
7
43
  export const applyDimensionToStyleBucket = ({
8
44
  styleBucket,
9
45
  axis,
10
46
  dimension,
11
47
  fillValue,
12
48
  allowFlexGrow = false,
49
+ flexMinDimension = "0",
13
50
  lockBounds = true,
14
51
  }) => {
52
+ const resetWidthFlexBasisState = () => {
53
+ if (!allowFlexGrow || axis !== "width") {
54
+ return;
55
+ }
56
+ styleBucket["flex-grow"] = "0";
57
+ styleBucket["flex-shrink"] = "1";
58
+ styleBucket["flex-basis"] = "auto";
59
+ };
60
+
61
+ const clearAxisBounds = () => {
62
+ styleBucket[`min-${axis}`] = "unset";
63
+ styleBucket[`max-${axis}`] = "unset";
64
+ };
65
+
15
66
  if (dimension === undefined) {
16
67
  return;
17
68
  }
18
69
 
19
70
  if (dimension === "f") {
71
+ resetWidthFlexBasisState();
20
72
  styleBucket[axis] = fillValue;
73
+ clearAxisBounds();
21
74
  return;
22
75
  }
23
76
 
24
77
  if (allowFlexGrow && isFlexGrowDimension(dimension)) {
25
78
  styleBucket["flex-grow"] = dimension.slice(0, -2);
26
79
  styleBucket["flex-basis"] = "0%";
80
+ styleBucket[`min-${axis}`] = flexMinDimension;
81
+ styleBucket[`max-${axis}`] = "unset";
82
+ return;
83
+ }
84
+
85
+ const flexBasis = allowFlexGrow ? parseFlexBasisDimension(dimension) : null;
86
+ if (flexBasis) {
87
+ styleBucket["flex-grow"] = "0";
88
+ styleBucket["flex-shrink"] = "0";
89
+ styleBucket["flex-basis"] = toFlexBasisCss({
90
+ ...flexBasis,
91
+ gapVar: "var(--rtgl-flex-gap, 0px)",
92
+ });
93
+ styleBucket[`min-${axis}`] = flexMinDimension;
94
+ styleBucket[`max-${axis}`] = "unset";
27
95
  return;
28
96
  }
29
97
 
98
+ resetWidthFlexBasisState();
30
99
  styleBucket[axis] = dimension;
31
100
  if (lockBounds) {
32
101
  styleBucket[`min-${axis}`] = dimension;
@@ -52,14 +121,29 @@ export const applyInlineWidthDimension = ({
52
121
  if (allowFlexGrow && isFlexGrowDimension(width)) {
53
122
  style.width = "";
54
123
  style.flexGrow = width.slice(0, -2);
124
+ style.flexShrink = "";
55
125
  style.flexBasis = "0%";
56
126
  style.minWidth = flexMinWidth;
57
127
  return;
58
128
  }
59
129
 
130
+ const inlineFlexBasis = allowFlexGrow ? parseFlexBasisDimension(width) : null;
131
+ if (inlineFlexBasis) {
132
+ style.width = "";
133
+ style.flexGrow = "0";
134
+ style.flexShrink = "0";
135
+ style.flexBasis = toFlexBasisCss({
136
+ ...inlineFlexBasis,
137
+ gapVar: "var(--rtgl-flex-gap, 0px)",
138
+ });
139
+ style.minWidth = flexMinWidth;
140
+ return;
141
+ }
142
+
60
143
  if (width != null) {
61
144
  style.width = width;
62
145
  style.flexGrow = "";
146
+ style.flexShrink = "";
63
147
  style.flexBasis = "";
64
148
  style.minWidth = "";
65
149
  return;
@@ -67,6 +151,7 @@ export const applyInlineWidthDimension = ({
67
151
 
68
152
  style.width = "";
69
153
  style.flexGrow = "";
154
+ style.flexShrink = "";
70
155
  style.flexBasis = "";
71
156
  style.minWidth = "";
72
157
  };
@@ -6,3 +6,75 @@ export const createResponsiveStyleBuckets = () => {
6
6
  return acc;
7
7
  }, {});
8
8
  };
9
+
10
+ const responsiveBreakpointsSmallToLarge = ["sm", "md", "lg", "xl"];
11
+
12
+ const getResponsiveAttributeName = ({ size, attr }) => {
13
+ return size === "default" ? attr : `${size}-${attr}`;
14
+ };
15
+
16
+ export const getResponsiveFallbackSizes = ({
17
+ size,
18
+ includeDefault = true,
19
+ }) => {
20
+ if (size === "default") {
21
+ return ["default"];
22
+ }
23
+
24
+ const sizeIndex = responsiveBreakpointsSmallToLarge.indexOf(size);
25
+ if (sizeIndex === -1) {
26
+ return includeDefault ? ["default"] : [];
27
+ }
28
+
29
+ const fallbackSizes = responsiveBreakpointsSmallToLarge.slice(sizeIndex);
30
+ if (includeDefault) {
31
+ fallbackSizes.push("default");
32
+ }
33
+
34
+ return fallbackSizes;
35
+ };
36
+
37
+ export const getResponsiveAttribute = ({
38
+ element,
39
+ size,
40
+ attr,
41
+ includeDefault = true,
42
+ }) => {
43
+ const fallbackSizes = getResponsiveFallbackSizes({
44
+ size,
45
+ includeDefault,
46
+ });
47
+
48
+ for (const fallbackSize of fallbackSizes) {
49
+ const attrName = getResponsiveAttributeName({
50
+ size: fallbackSize,
51
+ attr,
52
+ });
53
+ const value = element.getAttribute(attrName);
54
+ if (value !== null) {
55
+ return value;
56
+ }
57
+ }
58
+
59
+ return null;
60
+ };
61
+
62
+ export const hasResponsiveAttribute = ({
63
+ element,
64
+ size,
65
+ attr,
66
+ includeDefault = true,
67
+ }) => {
68
+ const fallbackSizes = getResponsiveFallbackSizes({
69
+ size,
70
+ includeDefault,
71
+ });
72
+
73
+ return fallbackSizes.some((fallbackSize) => {
74
+ const attrName = getResponsiveAttributeName({
75
+ size: fallbackSize,
76
+ attr,
77
+ });
78
+ return element.hasAttribute(attrName);
79
+ });
80
+ };
package/src/common.js CHANGED
@@ -24,9 +24,9 @@ const styleMap = {
24
24
  p: "padding",
25
25
  ph: "padding-left padding-right",
26
26
  pv: "padding-top padding-bottom",
27
- g: "gap",
28
- gv: "row-gap",
29
- gh: "column-gap",
27
+ g: "gap --rtgl-flex-gap",
28
+ gv: "row-gap --rtgl-flex-gap",
29
+ gh: "column-gap --rtgl-flex-gap",
30
30
  bw: "border-width",
31
31
  bwt: "border-top-width",
32
32
  bwr: "border-right-width",
@@ -152,7 +152,7 @@ const endsWithFlexGrowUnit = (inputStr) => {
152
152
  };
153
153
 
154
154
  const dimensionWithUnit = (dimension) => {
155
- if (dimension === undefined) {
155
+ if (dimension === undefined || dimension === null) {
156
156
  return;
157
157
  }
158
158
 
@@ -253,6 +253,8 @@ export {
253
253
  export {
254
254
  responsiveStyleSizes,
255
255
  createResponsiveStyleBuckets,
256
+ getResponsiveAttribute,
257
+ hasResponsiveAttribute,
256
258
  } from "./common/responsive.js";
257
259
 
258
260
  export {
@@ -30,7 +30,7 @@ propsSchema:
30
30
  testId:
31
31
  type: string
32
32
  open:
33
- type: string
33
+ type: boolean
34
34
  x:
35
35
  type: string
36
36
  'y':