@orion-studios/payload-studio 0.6.0-beta.114 → 0.6.0-beta.115

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.
@@ -1247,6 +1247,53 @@ var decorateBuilderColorEyeDroppers = (root = document) => {
1247
1247
  swatch.insertAdjacentElement("afterend", button);
1248
1248
  });
1249
1249
  };
1250
+ var decorateBuilderNumericSteppers = (root = document) => {
1251
+ const panel = document.getElementById("orion-builder-v2-styles");
1252
+ if (!panel || !("querySelector" in root)) {
1253
+ return;
1254
+ }
1255
+ stepperProperties.forEach((property) => {
1256
+ const control = panel.querySelector(`.gjs-sm-property__${CSS.escape(property)}`);
1257
+ const field = control?.querySelector(".gjs-field");
1258
+ const input = field?.querySelector("input");
1259
+ if (!field || !input || field.querySelector(".orion-builder-v2-stepper")) {
1260
+ return;
1261
+ }
1262
+ field.classList.add("has-orion-builder-stepper");
1263
+ const stepper = document.createElement("span");
1264
+ stepper.className = "orion-builder-v2-stepper";
1265
+ const updateValue = (direction) => {
1266
+ const current = Number.parseFloat(input.value || "0");
1267
+ const next = Number.isFinite(current) ? current + direction : direction;
1268
+ input.value = Number.isInteger(next) ? String(next) : String(Number(next.toFixed(2)));
1269
+ input.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertText" }));
1270
+ input.dispatchEvent(new Event("change", { bubbles: true }));
1271
+ };
1272
+ [
1273
+ { className: "is-up", direction: 1, label: "Increase", text: "\u25B2" },
1274
+ { className: "is-down", direction: -1, label: "Decrease", text: "\u25BC" }
1275
+ ].forEach((step) => {
1276
+ const button = document.createElement("button");
1277
+ button.type = "button";
1278
+ button.className = `orion-builder-v2-stepper-button ${step.className}`;
1279
+ button.setAttribute("aria-label", `${step.label} ${property.replace(/-/g, " ")}`);
1280
+ button.textContent = step.text;
1281
+ button.addEventListener("click", (event) => {
1282
+ event.preventDefault();
1283
+ event.stopPropagation();
1284
+ updateValue(step.direction);
1285
+ input.focus();
1286
+ });
1287
+ stepper.appendChild(button);
1288
+ });
1289
+ field.appendChild(stepper);
1290
+ });
1291
+ };
1292
+ var decorateBuilderControls = (root = document) => {
1293
+ decorateBuilderSettingHelp(root);
1294
+ decorateBuilderColorEyeDroppers(root);
1295
+ decorateBuilderNumericSteppers(root);
1296
+ };
1250
1297
  var closeBuilderHelpPopovers = (except) => {
1251
1298
  document.querySelectorAll(".is-builder-help-open").forEach((element) => {
1252
1299
  if (element !== except) {
@@ -1557,6 +1604,11 @@ var readStylePanelColor = (property) => {
1557
1604
  return swatchColor;
1558
1605
  };
1559
1606
  var readStylePanelRadio = (property) => (readStylePanelValue(property)?.querySelector("input:checked")?.value || "").trim();
1607
+ var propertyNameFromStyleControl = (element) => {
1608
+ const property = element?.closest(".gjs-sm-property");
1609
+ const className = Array.from(property?.classList || []).find((name) => name.startsWith("gjs-sm-property__"));
1610
+ return className?.replace(/^gjs-sm-property__/, "") || "";
1611
+ };
1560
1612
  var writeStylePanelLength = (property, value) => {
1561
1613
  const control = readStylePanelValue(property);
1562
1614
  const input = control?.querySelector("input");
@@ -1588,6 +1640,56 @@ var spacingTargetForComponent = (component) => {
1588
1640
  const element = component?.getEl?.();
1589
1641
  return element || null;
1590
1642
  };
1643
+ var liveStyleProperties = /* @__PURE__ */ new Set([
1644
+ "align-items",
1645
+ "bottom",
1646
+ "flex-direction",
1647
+ "flex-wrap",
1648
+ "font-size",
1649
+ "font-weight",
1650
+ "gap",
1651
+ "height",
1652
+ "justify-content",
1653
+ "left",
1654
+ "letter-spacing",
1655
+ "line-height",
1656
+ "margin",
1657
+ "margin-bottom",
1658
+ "margin-left",
1659
+ "margin-right",
1660
+ "margin-top",
1661
+ "min-height",
1662
+ "opacity",
1663
+ "padding",
1664
+ "padding-bottom",
1665
+ "padding-left",
1666
+ "padding-right",
1667
+ "padding-top",
1668
+ "right",
1669
+ "top",
1670
+ "width"
1671
+ ]);
1672
+ var stepperProperties = /* @__PURE__ */ new Set([
1673
+ "bottom",
1674
+ "font-size",
1675
+ "gap",
1676
+ "height",
1677
+ "left",
1678
+ "letter-spacing",
1679
+ "line-height",
1680
+ "margin-bottom",
1681
+ "margin-left",
1682
+ "margin-right",
1683
+ "margin-top",
1684
+ "min-height",
1685
+ "padding-bottom",
1686
+ "padding-left",
1687
+ "padding-right",
1688
+ "padding-top",
1689
+ "right",
1690
+ "top",
1691
+ "width"
1692
+ ]);
1591
1693
  var hasExplicitHorizontalAlign = (block) => {
1592
1694
  const settings = readNestedRecord(block, "settings");
1593
1695
  const typography = readNestedRecord(settings, "typography");
@@ -2030,7 +2132,7 @@ function GrapesPageEditor({
2030
2132
  setSelectionSummary(summarizeSelectedComponent(component));
2031
2133
  setQuickLayoutState(readQuickLayoutState(component));
2032
2134
  setDetailedLayoutControlState(readDetailedLayoutControlState(component));
2033
- window.requestAnimationFrame(() => decorateBuilderSettingHelp());
2135
+ window.requestAnimationFrame(() => decorateBuilderControls());
2034
2136
  };
2035
2137
  const applySelectedStyle = (style) => {
2036
2138
  const component = selectedComponentRef.current;
@@ -2051,6 +2153,21 @@ function GrapesPageEditor({
2051
2153
  rememberComponentSnapshot(component);
2052
2154
  refreshSelectedState(component);
2053
2155
  };
2156
+ const applyLiveStylePanelValue = (target) => {
2157
+ const property = propertyNameFromStyleControl(target);
2158
+ if (!property || !liveStyleProperties.has(property)) {
2159
+ return;
2160
+ }
2161
+ const selected = getCurrentOrionBlockTarget(getCurrentStyleTarget());
2162
+ if (!selected) {
2163
+ return;
2164
+ }
2165
+ const value = property === "font-weight" ? normalizeFontWeightValue(readStylePanelSelect(property)) || readStylePanelInput(property) : property === "opacity" ? readStylePanelInput(property) : readStylePanelLength(property) || readStylePanelInput(property) || readStylePanelSelect(property) || readStylePanelRadio(property);
2166
+ selectedComponentRef.current = selected;
2167
+ lastSelectedComponentRef.current = selected;
2168
+ selected.addStyle?.({ [property]: value });
2169
+ editorRef.current?.select?.(selected);
2170
+ };
2054
2171
  const updateSelectedOrionBlock = (updates) => {
2055
2172
  const component = selectedComponentRef.current;
2056
2173
  if (!component) {
@@ -2541,6 +2658,7 @@ function GrapesPageEditor({
2541
2658
  if (!sidebarPointerActiveRef.current && !activeElement?.closest("#orion-builder-v2-styles")) {
2542
2659
  return;
2543
2660
  }
2661
+ applyLiveStylePanelValue(target);
2544
2662
  stylePanelEditActiveRef.current = true;
2545
2663
  if (!stylePanelHistoryBeforeRef.current) {
2546
2664
  stylePanelHistoryBeforeRef.current = snapshotComponent(getCurrentOrionBlockTarget(getCurrentStyleTarget()));
@@ -2836,7 +2954,7 @@ function GrapesPageEditor({
2836
2954
  setSelectedDevice(editor.getDevice() || "desktop");
2837
2955
  runValidation(editor);
2838
2956
  updateHistoryState(editor);
2839
- decorateBuilderSettingHelp();
2957
+ decorateBuilderControls();
2840
2958
  setLoading(false);
2841
2959
  } catch (initError) {
2842
2960
  setError(initError instanceof Error ? initError.message : "Could not load the website builder.");
@@ -2946,8 +3064,7 @@ function GrapesPageEditor({
2946
3064
  saveRef.current = save;
2947
3065
  }, [saving]);
2948
3066
  (0, import_react.useEffect)(() => {
2949
- decorateBuilderSettingHelp();
2950
- decorateBuilderColorEyeDroppers();
3067
+ decorateBuilderControls();
2951
3068
  const refreshControls = () => refreshSelectedState(selectedComponentRef.current);
2952
3069
  const onStylePanelInput = (event) => {
2953
3070
  const target = event.target;
@@ -2956,6 +3073,7 @@ function GrapesPageEditor({
2956
3073
  if (!sidebarPointerActiveRef.current && !activeElement?.closest("#orion-builder-v2-styles")) {
2957
3074
  return;
2958
3075
  }
3076
+ applyLiveStylePanelValue(target);
2959
3077
  syncStylePanelChange();
2960
3078
  }
2961
3079
  };
@@ -3006,8 +3124,7 @@ function GrapesPageEditor({
3006
3124
  openBuilderHelpPopover(helpTrigger, wrapper, willOpen);
3007
3125
  };
3008
3126
  const observer = new MutationObserver(() => {
3009
- decorateBuilderSettingHelp();
3010
- decorateBuilderColorEyeDroppers();
3127
+ decorateBuilderControls();
3011
3128
  });
3012
3129
  observer.observe(document.body, {
3013
3130
  childList: true,
@@ -1123,6 +1123,53 @@ var decorateBuilderColorEyeDroppers = (root = document) => {
1123
1123
  swatch.insertAdjacentElement("afterend", button);
1124
1124
  });
1125
1125
  };
1126
+ var decorateBuilderNumericSteppers = (root = document) => {
1127
+ const panel = document.getElementById("orion-builder-v2-styles");
1128
+ if (!panel || !("querySelector" in root)) {
1129
+ return;
1130
+ }
1131
+ stepperProperties.forEach((property) => {
1132
+ const control = panel.querySelector(`.gjs-sm-property__${CSS.escape(property)}`);
1133
+ const field = control?.querySelector(".gjs-field");
1134
+ const input = field?.querySelector("input");
1135
+ if (!field || !input || field.querySelector(".orion-builder-v2-stepper")) {
1136
+ return;
1137
+ }
1138
+ field.classList.add("has-orion-builder-stepper");
1139
+ const stepper = document.createElement("span");
1140
+ stepper.className = "orion-builder-v2-stepper";
1141
+ const updateValue = (direction) => {
1142
+ const current = Number.parseFloat(input.value || "0");
1143
+ const next = Number.isFinite(current) ? current + direction : direction;
1144
+ input.value = Number.isInteger(next) ? String(next) : String(Number(next.toFixed(2)));
1145
+ input.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertText" }));
1146
+ input.dispatchEvent(new Event("change", { bubbles: true }));
1147
+ };
1148
+ [
1149
+ { className: "is-up", direction: 1, label: "Increase", text: "\u25B2" },
1150
+ { className: "is-down", direction: -1, label: "Decrease", text: "\u25BC" }
1151
+ ].forEach((step) => {
1152
+ const button = document.createElement("button");
1153
+ button.type = "button";
1154
+ button.className = `orion-builder-v2-stepper-button ${step.className}`;
1155
+ button.setAttribute("aria-label", `${step.label} ${property.replace(/-/g, " ")}`);
1156
+ button.textContent = step.text;
1157
+ button.addEventListener("click", (event) => {
1158
+ event.preventDefault();
1159
+ event.stopPropagation();
1160
+ updateValue(step.direction);
1161
+ input.focus();
1162
+ });
1163
+ stepper.appendChild(button);
1164
+ });
1165
+ field.appendChild(stepper);
1166
+ });
1167
+ };
1168
+ var decorateBuilderControls = (root = document) => {
1169
+ decorateBuilderSettingHelp(root);
1170
+ decorateBuilderColorEyeDroppers(root);
1171
+ decorateBuilderNumericSteppers(root);
1172
+ };
1126
1173
  var closeBuilderHelpPopovers = (except) => {
1127
1174
  document.querySelectorAll(".is-builder-help-open").forEach((element) => {
1128
1175
  if (element !== except) {
@@ -1433,6 +1480,11 @@ var readStylePanelColor = (property) => {
1433
1480
  return swatchColor;
1434
1481
  };
1435
1482
  var readStylePanelRadio = (property) => (readStylePanelValue(property)?.querySelector("input:checked")?.value || "").trim();
1483
+ var propertyNameFromStyleControl = (element) => {
1484
+ const property = element?.closest(".gjs-sm-property");
1485
+ const className = Array.from(property?.classList || []).find((name) => name.startsWith("gjs-sm-property__"));
1486
+ return className?.replace(/^gjs-sm-property__/, "") || "";
1487
+ };
1436
1488
  var writeStylePanelLength = (property, value) => {
1437
1489
  const control = readStylePanelValue(property);
1438
1490
  const input = control?.querySelector("input");
@@ -1464,6 +1516,56 @@ var spacingTargetForComponent = (component) => {
1464
1516
  const element = component?.getEl?.();
1465
1517
  return element || null;
1466
1518
  };
1519
+ var liveStyleProperties = /* @__PURE__ */ new Set([
1520
+ "align-items",
1521
+ "bottom",
1522
+ "flex-direction",
1523
+ "flex-wrap",
1524
+ "font-size",
1525
+ "font-weight",
1526
+ "gap",
1527
+ "height",
1528
+ "justify-content",
1529
+ "left",
1530
+ "letter-spacing",
1531
+ "line-height",
1532
+ "margin",
1533
+ "margin-bottom",
1534
+ "margin-left",
1535
+ "margin-right",
1536
+ "margin-top",
1537
+ "min-height",
1538
+ "opacity",
1539
+ "padding",
1540
+ "padding-bottom",
1541
+ "padding-left",
1542
+ "padding-right",
1543
+ "padding-top",
1544
+ "right",
1545
+ "top",
1546
+ "width"
1547
+ ]);
1548
+ var stepperProperties = /* @__PURE__ */ new Set([
1549
+ "bottom",
1550
+ "font-size",
1551
+ "gap",
1552
+ "height",
1553
+ "left",
1554
+ "letter-spacing",
1555
+ "line-height",
1556
+ "margin-bottom",
1557
+ "margin-left",
1558
+ "margin-right",
1559
+ "margin-top",
1560
+ "min-height",
1561
+ "padding-bottom",
1562
+ "padding-left",
1563
+ "padding-right",
1564
+ "padding-top",
1565
+ "right",
1566
+ "top",
1567
+ "width"
1568
+ ]);
1467
1569
  var hasExplicitHorizontalAlign = (block) => {
1468
1570
  const settings = readNestedRecord(block, "settings");
1469
1571
  const typography = readNestedRecord(settings, "typography");
@@ -1906,7 +2008,7 @@ function GrapesPageEditor({
1906
2008
  setSelectionSummary(summarizeSelectedComponent(component));
1907
2009
  setQuickLayoutState(readQuickLayoutState(component));
1908
2010
  setDetailedLayoutControlState(readDetailedLayoutControlState(component));
1909
- window.requestAnimationFrame(() => decorateBuilderSettingHelp());
2011
+ window.requestAnimationFrame(() => decorateBuilderControls());
1910
2012
  };
1911
2013
  const applySelectedStyle = (style) => {
1912
2014
  const component = selectedComponentRef.current;
@@ -1927,6 +2029,21 @@ function GrapesPageEditor({
1927
2029
  rememberComponentSnapshot(component);
1928
2030
  refreshSelectedState(component);
1929
2031
  };
2032
+ const applyLiveStylePanelValue = (target) => {
2033
+ const property = propertyNameFromStyleControl(target);
2034
+ if (!property || !liveStyleProperties.has(property)) {
2035
+ return;
2036
+ }
2037
+ const selected = getCurrentOrionBlockTarget(getCurrentStyleTarget());
2038
+ if (!selected) {
2039
+ return;
2040
+ }
2041
+ const value = property === "font-weight" ? normalizeFontWeightValue(readStylePanelSelect(property)) || readStylePanelInput(property) : property === "opacity" ? readStylePanelInput(property) : readStylePanelLength(property) || readStylePanelInput(property) || readStylePanelSelect(property) || readStylePanelRadio(property);
2042
+ selectedComponentRef.current = selected;
2043
+ lastSelectedComponentRef.current = selected;
2044
+ selected.addStyle?.({ [property]: value });
2045
+ editorRef.current?.select?.(selected);
2046
+ };
1930
2047
  const updateSelectedOrionBlock = (updates) => {
1931
2048
  const component = selectedComponentRef.current;
1932
2049
  if (!component) {
@@ -2417,6 +2534,7 @@ function GrapesPageEditor({
2417
2534
  if (!sidebarPointerActiveRef.current && !activeElement?.closest("#orion-builder-v2-styles")) {
2418
2535
  return;
2419
2536
  }
2537
+ applyLiveStylePanelValue(target);
2420
2538
  stylePanelEditActiveRef.current = true;
2421
2539
  if (!stylePanelHistoryBeforeRef.current) {
2422
2540
  stylePanelHistoryBeforeRef.current = snapshotComponent(getCurrentOrionBlockTarget(getCurrentStyleTarget()));
@@ -2712,7 +2830,7 @@ function GrapesPageEditor({
2712
2830
  setSelectedDevice(editor.getDevice() || "desktop");
2713
2831
  runValidation(editor);
2714
2832
  updateHistoryState(editor);
2715
- decorateBuilderSettingHelp();
2833
+ decorateBuilderControls();
2716
2834
  setLoading(false);
2717
2835
  } catch (initError) {
2718
2836
  setError(initError instanceof Error ? initError.message : "Could not load the website builder.");
@@ -2822,8 +2940,7 @@ function GrapesPageEditor({
2822
2940
  saveRef.current = save;
2823
2941
  }, [saving]);
2824
2942
  useEffect(() => {
2825
- decorateBuilderSettingHelp();
2826
- decorateBuilderColorEyeDroppers();
2943
+ decorateBuilderControls();
2827
2944
  const refreshControls = () => refreshSelectedState(selectedComponentRef.current);
2828
2945
  const onStylePanelInput = (event) => {
2829
2946
  const target = event.target;
@@ -2832,6 +2949,7 @@ function GrapesPageEditor({
2832
2949
  if (!sidebarPointerActiveRef.current && !activeElement?.closest("#orion-builder-v2-styles")) {
2833
2950
  return;
2834
2951
  }
2952
+ applyLiveStylePanelValue(target);
2835
2953
  syncStylePanelChange();
2836
2954
  }
2837
2955
  };
@@ -2882,8 +3000,7 @@ function GrapesPageEditor({
2882
3000
  openBuilderHelpPopover(helpTrigger, wrapper, willOpen);
2883
3001
  };
2884
3002
  const observer = new MutationObserver(() => {
2885
- decorateBuilderSettingHelp();
2886
- decorateBuilderColorEyeDroppers();
3003
+ decorateBuilderControls();
2887
3004
  });
2888
3005
  observer.observe(document.body, {
2889
3006
  childList: true,
@@ -1365,6 +1365,48 @@
1365
1365
  padding-right: 8px;
1366
1366
  }
1367
1367
 
1368
+ .orion-builder-v2-editor .gjs-field.has-orion-builder-stepper {
1369
+ align-items: stretch;
1370
+ display: grid !important;
1371
+ grid-template-columns: minmax(0, 1fr) auto auto;
1372
+ }
1373
+
1374
+ .orion-builder-v2-editor .gjs-field.has-orion-builder-stepper input {
1375
+ min-width: 0;
1376
+ }
1377
+
1378
+ .orion-builder-v2-stepper {
1379
+ align-self: stretch;
1380
+ border-left: 1px solid rgba(214, 183, 161, 0.72);
1381
+ display: grid;
1382
+ grid-template-rows: 1fr 1fr;
1383
+ min-height: 34px;
1384
+ width: 24px;
1385
+ }
1386
+
1387
+ .orion-builder-v2-stepper-button {
1388
+ align-items: center;
1389
+ appearance: none;
1390
+ background: #fff6ec;
1391
+ border: 0;
1392
+ color: #7a543e;
1393
+ cursor: pointer;
1394
+ display: inline-flex;
1395
+ font: 800 8px/1 var(--font-xo-sans, ui-sans-serif, system-ui, sans-serif);
1396
+ justify-content: center;
1397
+ min-height: 0;
1398
+ padding: 0;
1399
+ }
1400
+
1401
+ .orion-builder-v2-stepper-button + .orion-builder-v2-stepper-button {
1402
+ border-top: 1px solid rgba(214, 183, 161, 0.72);
1403
+ }
1404
+
1405
+ .orion-builder-v2-stepper-button:hover {
1406
+ background: #f4e2d3;
1407
+ color: #1f2d4d;
1408
+ }
1409
+
1368
1410
  .orion-builder-v2-editor .gjs-field-color {
1369
1411
  cursor: pointer;
1370
1412
  display: grid !important;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-studios/payload-studio",
3
- "version": "0.6.0-beta.114",
3
+ "version": "0.6.0-beta.115",
4
4
  "description": "Base CMS, builder, and custom admin toolkit for Orion Studios websites",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",