@astuteo/breakout-grid 5.1.1 → 5.1.2
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
"use strict";
|
|
3
|
-
const VERSION = `v${"5.1.
|
|
3
|
+
const VERSION = `v${"5.1.2"} lite`;
|
|
4
4
|
const LOREM_CONTENT = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
|
|
5
5
|
|
|
6
6
|
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
"use strict";
|
|
3
|
-
const VERSION = `v${"5.1.
|
|
3
|
+
const VERSION = `v${"5.1.2"}`;
|
|
4
4
|
const LOREM_CONTENT = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.
|
|
5
5
|
|
|
6
6
|
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.`;
|
|
@@ -12,19 +12,16 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
12
12
|
{ name: "content", label: "Content", className: ".col-content", color: "rgba(168, 85, 247, 0.25)", borderColor: "rgb(168, 85, 247)" }
|
|
13
13
|
];
|
|
14
14
|
const CONFIG_OPTIONS = {
|
|
15
|
-
// Base measurements
|
|
16
15
|
baseGap: { value: "1rem", desc: "Minimum gap between columns. Use rem.", cssVar: "--config-base-gap", liveVar: "--base-gap" },
|
|
17
16
|
maxGap: { value: "15rem", desc: "Maximum gap cap for ultra-wide. Use rem.", cssVar: "--config-max-gap", liveVar: "--max-gap" },
|
|
18
|
-
contentMin: { value: "
|
|
19
|
-
contentMax: { value: "
|
|
17
|
+
contentMin: { value: "50rem", desc: "Min width for content column (~848px). Use rem.", cssVar: "--config-content-min", liveVar: "--content-min" },
|
|
18
|
+
contentMax: { value: "55rem", desc: "Max width for content column (~976px). Use rem.", cssVar: "--config-content-max", liveVar: "--content-max" },
|
|
20
19
|
contentBase: { value: "75vw", desc: "Preferred width for content (fluid). Use vw.", cssVar: "--config-content-base", liveVar: "--content-base" },
|
|
21
|
-
// Track widths
|
|
22
20
|
popoutWidth: { value: "5rem", desc: "Popout extends beyond content. Use rem.", cssVar: "--config-popout", liveVar: null },
|
|
23
21
|
featureMin: { value: "0rem", desc: "Minimum feature track width (floor)", cssVar: "--config-feature-min", liveVar: null },
|
|
24
22
|
featureScale: { value: "12vw", desc: "Fluid feature track scaling", cssVar: "--config-feature-scale", liveVar: null },
|
|
25
23
|
featureMax: { value: "12rem", desc: "Maximum feature track width (ceiling)", cssVar: "--config-feature-max", liveVar: null },
|
|
26
24
|
fullLimit: { value: "115rem", desc: "Max width for col-full-limit. Use rem.", cssVar: "--config-full-limit", liveVar: "--full-limit" },
|
|
27
|
-
// Default column
|
|
28
25
|
defaultCol: { value: "content", desc: "Default column when no col-* class", type: "select", options: ["content", "popout", "feature", "full"], cssVar: "--config-default-col" }
|
|
29
26
|
};
|
|
30
27
|
const GAP_SCALE_OPTIONS = {
|
|
@@ -43,7 +40,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
43
40
|
};
|
|
44
41
|
function createInitialState() {
|
|
45
42
|
return {
|
|
46
|
-
// UI State
|
|
47
43
|
isVisible: false,
|
|
48
44
|
showLabels: true,
|
|
49
45
|
showClassNames: true,
|
|
@@ -65,38 +61,28 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
65
61
|
editorPos: { x: 20, y: 100 },
|
|
66
62
|
isDragging: false,
|
|
67
63
|
dragOffset: { x: 0, y: 0 },
|
|
68
|
-
// Column resize drag state
|
|
69
64
|
resizingColumn: null,
|
|
70
65
|
resizeStartX: 0,
|
|
71
66
|
resizeStartValue: 0,
|
|
72
|
-
// Panel collapse state
|
|
73
67
|
controlPanelCollapsed: false,
|
|
74
68
|
configEditorCollapsed: false,
|
|
75
|
-
//
|
|
76
|
-
columnWidths: {
|
|
77
|
-
full: 0,
|
|
78
|
-
"full-limit": 0,
|
|
79
|
-
feature: 0,
|
|
80
|
-
popout: 0,
|
|
81
|
-
content: 0,
|
|
82
|
-
center: 0
|
|
83
|
-
},
|
|
84
|
-
// Current breakpoint for gap scale (mobile, lg, xl)
|
|
69
|
+
// Pre-initialized for Alpine reactivity
|
|
70
|
+
columnWidths: { full: 0, "full-limit": 0, feature: 0, popout: 0, content: 0, center: 0 },
|
|
85
71
|
currentBreakpoint: "mobile",
|
|
86
|
-
// Spacing panel state
|
|
87
72
|
spacingPanelCollapsed: false,
|
|
88
73
|
spacingPanelPos: { x: 16, y: 16 },
|
|
89
74
|
isDraggingSpacing: false,
|
|
90
75
|
dragOffsetSpacing: { x: 0, y: 0 },
|
|
91
|
-
// Restore config modal
|
|
92
76
|
showRestoreModal: false,
|
|
93
77
|
restoreInput: "",
|
|
94
78
|
restoreError: null,
|
|
95
|
-
|
|
96
|
-
|
|
79
|
+
sectionCopied: null,
|
|
80
|
+
showCloseWarningModal: false,
|
|
81
|
+
gridOpacity: 0.8,
|
|
82
|
+
backdropOpacity: 0.85
|
|
97
83
|
};
|
|
98
84
|
}
|
|
99
|
-
const BUILD_VERSION = "5.1.
|
|
85
|
+
const BUILD_VERSION = "5.1.2";
|
|
100
86
|
function generateCSSExport(c, version = BUILD_VERSION) {
|
|
101
87
|
var _a, _b, _c, _d, _e;
|
|
102
88
|
const VERSION2 = version;
|
|
@@ -763,7 +749,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
763
749
|
`;
|
|
764
750
|
}
|
|
765
751
|
const methods = {
|
|
766
|
-
// Initialize
|
|
767
752
|
init() {
|
|
768
753
|
const saved = localStorage.getItem("breakoutGridVisualizerVisible");
|
|
769
754
|
if (saved !== null) {
|
|
@@ -818,12 +803,10 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
818
803
|
this.updateCurrentBreakpoint();
|
|
819
804
|
console.log("Breakout Grid Visualizer loaded. Press Ctrl/Cmd + G to toggle.");
|
|
820
805
|
},
|
|
821
|
-
// Toggle visibility
|
|
822
806
|
toggle() {
|
|
823
807
|
this.isVisible = !this.isVisible;
|
|
824
808
|
localStorage.setItem("breakoutGridVisualizerVisible", this.isVisible);
|
|
825
809
|
},
|
|
826
|
-
// Update column widths by querying DOM elements
|
|
827
810
|
updateColumnWidths() {
|
|
828
811
|
this.$nextTick(() => {
|
|
829
812
|
this.gridAreas.forEach((area) => {
|
|
@@ -834,7 +817,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
834
817
|
});
|
|
835
818
|
});
|
|
836
819
|
},
|
|
837
|
-
// Detect current breakpoint based on viewport width
|
|
838
820
|
updateCurrentBreakpoint() {
|
|
839
821
|
const width = window.innerWidth;
|
|
840
822
|
if (width >= 1280) {
|
|
@@ -845,7 +827,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
845
827
|
this.currentBreakpoint = "mobile";
|
|
846
828
|
}
|
|
847
829
|
},
|
|
848
|
-
// Update --gap live based on current breakpoint and edit values
|
|
849
830
|
updateGapLive() {
|
|
850
831
|
const scaleKey = this.currentBreakpoint === "mobile" ? "default" : this.currentBreakpoint;
|
|
851
832
|
const base = this.editValues.baseGap || this.configOptions.baseGap.value;
|
|
@@ -854,7 +835,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
854
835
|
document.documentElement.style.setProperty("--gap", `clamp(${base}, ${scale}, ${max})`);
|
|
855
836
|
this.updateColumnWidths();
|
|
856
837
|
},
|
|
857
|
-
// Check if content width exceeds comfortable reading width (55rem)
|
|
858
838
|
getContentReadabilityWarning() {
|
|
859
839
|
const contentMax = parseFloat(this.editValues.contentMax || this.configOptions.contentMax.value);
|
|
860
840
|
if (contentMax > 55) {
|
|
@@ -862,7 +842,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
862
842
|
}
|
|
863
843
|
return null;
|
|
864
844
|
},
|
|
865
|
-
// Check if configured track widths would exceed viewport
|
|
866
845
|
getTrackOverflowWarning() {
|
|
867
846
|
const contentMax = parseFloat(this.editValues.contentMax || this.configOptions.contentMax.value) * 16;
|
|
868
847
|
const featureMax = parseFloat(this.editValues.featureMax || this.configOptions.featureMax.value) * 16;
|
|
@@ -875,12 +854,10 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
875
854
|
}
|
|
876
855
|
return null;
|
|
877
856
|
},
|
|
878
|
-
// Get computed CSS variable value
|
|
879
857
|
getCSSVariable(varName) {
|
|
880
858
|
const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
|
|
881
859
|
return value || "Not set";
|
|
882
860
|
},
|
|
883
|
-
// Helper to load options from CSS variables
|
|
884
861
|
loadOptionsFromCSS(options, prefix = "") {
|
|
885
862
|
Object.keys(options).forEach((key) => {
|
|
886
863
|
const opt = options[key];
|
|
@@ -893,13 +870,11 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
893
870
|
}
|
|
894
871
|
});
|
|
895
872
|
},
|
|
896
|
-
// Load current values from CSS variables where available
|
|
897
873
|
loadCurrentValues() {
|
|
898
874
|
this.loadOptionsFromCSS(this.configOptions);
|
|
899
875
|
this.loadOptionsFromCSS(this.gapScaleOptions, "gapScale");
|
|
900
876
|
this.loadOptionsFromCSS(this.breakoutOptions, "breakout");
|
|
901
877
|
},
|
|
902
|
-
// Generate export config object
|
|
903
878
|
generateConfigExport() {
|
|
904
879
|
var _a, _b, _c, _d;
|
|
905
880
|
const config = {};
|
|
@@ -918,7 +893,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
918
893
|
};
|
|
919
894
|
return config;
|
|
920
895
|
},
|
|
921
|
-
// Format config object with single quotes for values, no quotes for keys
|
|
922
896
|
formatConfig(obj, indent = 2) {
|
|
923
897
|
const pad = " ".repeat(indent);
|
|
924
898
|
const lines = ["{"];
|
|
@@ -934,35 +908,14 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
934
908
|
lines.push("}");
|
|
935
909
|
return lines.join("\n");
|
|
936
910
|
},
|
|
937
|
-
// Section definitions for partial copying
|
|
938
911
|
configSections: {
|
|
939
|
-
content: {
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
},
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
label: "Default Column"
|
|
946
|
-
},
|
|
947
|
-
tracks: {
|
|
948
|
-
keys: ["popoutWidth", "fullLimit"],
|
|
949
|
-
label: "Track Widths"
|
|
950
|
-
},
|
|
951
|
-
feature: {
|
|
952
|
-
keys: ["featureMin", "featureScale", "featureMax"],
|
|
953
|
-
label: "Feature"
|
|
954
|
-
},
|
|
955
|
-
gap: {
|
|
956
|
-
keys: ["baseGap", "maxGap"],
|
|
957
|
-
nested: { gapScale: ["default", "lg", "xl"] },
|
|
958
|
-
label: "Gap"
|
|
959
|
-
},
|
|
960
|
-
breakout: {
|
|
961
|
-
keys: ["breakoutMin", "breakoutScale"],
|
|
962
|
-
label: "Breakout"
|
|
963
|
-
}
|
|
912
|
+
content: { keys: ["contentMin", "contentBase", "contentMax"], label: "Content" },
|
|
913
|
+
defaultCol: { keys: ["defaultCol"], label: "Default Column" },
|
|
914
|
+
tracks: { keys: ["popoutWidth", "fullLimit"], label: "Track Widths" },
|
|
915
|
+
feature: { keys: ["featureMin", "featureScale", "featureMax"], label: "Feature" },
|
|
916
|
+
gap: { keys: ["baseGap", "maxGap"], nested: { gapScale: ["default", "lg", "xl"] }, label: "Gap" },
|
|
917
|
+
breakout: { keys: ["breakoutMin", "breakoutScale"], label: "Breakout" }
|
|
964
918
|
},
|
|
965
|
-
// Copy a specific section to clipboard
|
|
966
919
|
copySection(sectionName) {
|
|
967
920
|
const section = this.configSections[sectionName];
|
|
968
921
|
if (!section) return;
|
|
@@ -990,7 +943,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
990
943
|
setTimeout(() => this.sectionCopied = null, 1500);
|
|
991
944
|
});
|
|
992
945
|
},
|
|
993
|
-
// Format config as flat key-value pairs (no wrapping braces)
|
|
994
946
|
formatConfigFlat(obj) {
|
|
995
947
|
const lines = [];
|
|
996
948
|
const entries = Object.entries(obj);
|
|
@@ -1004,7 +956,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1004
956
|
});
|
|
1005
957
|
return lines.join("\n");
|
|
1006
958
|
},
|
|
1007
|
-
// Copy config to clipboard as CSS variables
|
|
1008
959
|
copyConfig() {
|
|
1009
960
|
var _a, _b, _c, _d, _e;
|
|
1010
961
|
const config = this.generateConfigExport();
|
|
@@ -1045,7 +996,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1045
996
|
setTimeout(() => this.copySuccess = false, 2e3);
|
|
1046
997
|
});
|
|
1047
998
|
},
|
|
1048
|
-
// Generate and download standalone CSS file
|
|
1049
999
|
downloadCSS() {
|
|
1050
1000
|
const css = this.generateCSSExport(this.generateConfigExport());
|
|
1051
1001
|
const blob = new Blob([css], { type: "text/css" });
|
|
@@ -1056,7 +1006,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1056
1006
|
a.click();
|
|
1057
1007
|
URL.revokeObjectURL(url);
|
|
1058
1008
|
},
|
|
1059
|
-
// Parse CSS value into number and unit (e.g., "4rem" -> { num: 4, unit: "rem" })
|
|
1060
1009
|
parseValue(val) {
|
|
1061
1010
|
const match = String(val).match(/^([\d.]+)(.*)$/);
|
|
1062
1011
|
if (match) {
|
|
@@ -1064,29 +1013,23 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1064
1013
|
}
|
|
1065
1014
|
return { num: 0, unit: "rem" };
|
|
1066
1015
|
},
|
|
1067
|
-
// Get the numeric part of a config value
|
|
1068
1016
|
getNumericValue(key) {
|
|
1069
1017
|
const val = this.editValues[key] || this.configOptions[key].value;
|
|
1070
1018
|
return this.parseValue(val).num;
|
|
1071
1019
|
},
|
|
1072
|
-
// Get the unit part of a config value
|
|
1073
1020
|
getUnit(key) {
|
|
1074
1021
|
const val = this.editValues[key] || this.configOptions[key].value;
|
|
1075
1022
|
return this.parseValue(val).unit;
|
|
1076
1023
|
},
|
|
1077
|
-
// Check if a field should have unit selection (rem-based fields only)
|
|
1078
1024
|
hasUnitSelector(key) {
|
|
1079
1025
|
const unit = this.getUnit(key);
|
|
1080
1026
|
return unit === "rem" || unit === "ch" || unit === "px";
|
|
1081
1027
|
},
|
|
1082
|
-
// Available units for selection
|
|
1083
1028
|
unitOptions: ["rem", "ch", "px"],
|
|
1084
|
-
// Update just the unit, keeping the numeric value
|
|
1085
1029
|
updateUnit(key, newUnit) {
|
|
1086
1030
|
const num = this.getNumericValue(key);
|
|
1087
1031
|
this.updateConfigValue(key, num + newUnit);
|
|
1088
1032
|
},
|
|
1089
|
-
// Update just the numeric part, keeping the unit
|
|
1090
1033
|
updateNumericValue(key, num) {
|
|
1091
1034
|
if (key === "content" && num < 1) num = 1;
|
|
1092
1035
|
if (key === "baseGap" && num < 0) num = 0;
|
|
@@ -1095,7 +1038,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1095
1038
|
const unit = this.getUnit(key);
|
|
1096
1039
|
this.updateConfigValue(key, num + unit);
|
|
1097
1040
|
},
|
|
1098
|
-
// Generic getter for prefixed options (gapScale, breakout)
|
|
1099
1041
|
getPrefixedNumeric(prefix, options, key) {
|
|
1100
1042
|
const val = this.editValues[`${prefix}_${key}`] || options[key].value;
|
|
1101
1043
|
return this.parseValue(val).num;
|
|
@@ -1104,7 +1046,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1104
1046
|
const val = this.editValues[`${prefix}_${key}`] || options[key].value;
|
|
1105
1047
|
return this.parseValue(val).unit;
|
|
1106
1048
|
},
|
|
1107
|
-
// Gap scale helpers (use generic)
|
|
1108
1049
|
getGapScaleNumeric(key) {
|
|
1109
1050
|
return this.getPrefixedNumeric("gapScale", this.gapScaleOptions, key);
|
|
1110
1051
|
},
|
|
@@ -1117,7 +1058,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1117
1058
|
this.updateGapLive();
|
|
1118
1059
|
this.saveConfigToStorage();
|
|
1119
1060
|
},
|
|
1120
|
-
// Breakout helpers (use generic)
|
|
1121
1061
|
getBreakoutNumeric(key) {
|
|
1122
1062
|
return this.getPrefixedNumeric("breakout", this.breakoutOptions, key);
|
|
1123
1063
|
},
|
|
@@ -1130,19 +1070,16 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1130
1070
|
this.updateBreakoutLive();
|
|
1131
1071
|
this.saveConfigToStorage();
|
|
1132
1072
|
},
|
|
1133
|
-
// Update --breakout-padding live
|
|
1134
1073
|
updateBreakoutLive() {
|
|
1135
1074
|
const min = this.editValues.breakout_min || this.breakoutOptions.min.value;
|
|
1136
1075
|
const scale = this.editValues.breakout_scale || this.breakoutOptions.scale.value;
|
|
1137
1076
|
const max = this.editValues.popoutWidth || this.configOptions.popoutWidth.value;
|
|
1138
1077
|
document.documentElement.style.setProperty("--breakout-padding", `clamp(${min}, ${scale}, ${max})`);
|
|
1139
1078
|
},
|
|
1140
|
-
// Save current config to localStorage
|
|
1141
1079
|
saveConfigToStorage() {
|
|
1142
1080
|
const config = this.generateConfigExport();
|
|
1143
1081
|
localStorage.setItem("breakoutGridConfig", JSON.stringify(config));
|
|
1144
1082
|
},
|
|
1145
|
-
// Apply a config object (used by restore and localStorage load)
|
|
1146
1083
|
applyConfig(config) {
|
|
1147
1084
|
this.editMode = true;
|
|
1148
1085
|
Object.keys(this.configOptions).forEach((key) => {
|
|
@@ -1188,7 +1125,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1188
1125
|
}
|
|
1189
1126
|
this.updateColumnWidths();
|
|
1190
1127
|
},
|
|
1191
|
-
// Reset config to defaults and clear localStorage
|
|
1192
1128
|
resetConfigToDefaults() {
|
|
1193
1129
|
if (!confirm("Reset all config values to defaults?")) return;
|
|
1194
1130
|
localStorage.removeItem("breakoutGridConfig");
|
|
@@ -1196,7 +1132,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1196
1132
|
this.loadCurrentValues();
|
|
1197
1133
|
this.configCopied = false;
|
|
1198
1134
|
},
|
|
1199
|
-
// Update a config value (and live CSS var if applicable)
|
|
1200
1135
|
updateConfigValue(key, value) {
|
|
1201
1136
|
this.editValues[key] = value;
|
|
1202
1137
|
this.configCopied = false;
|
|
@@ -1222,15 +1157,12 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1222
1157
|
this.updateGapLive();
|
|
1223
1158
|
}
|
|
1224
1159
|
},
|
|
1225
|
-
// Select a grid area
|
|
1226
1160
|
selectArea(areaName) {
|
|
1227
1161
|
this.selectedArea = this.selectedArea === areaName ? null : areaName;
|
|
1228
1162
|
},
|
|
1229
|
-
// Check if area is selected
|
|
1230
1163
|
isSelected(areaName) {
|
|
1231
1164
|
return this.selectedArea === areaName;
|
|
1232
1165
|
},
|
|
1233
|
-
// Restore all CSS variable overrides to original values
|
|
1234
1166
|
restoreCSSVariables() {
|
|
1235
1167
|
Object.keys(this.configOptions).forEach((key) => {
|
|
1236
1168
|
const opt = this.configOptions[key];
|
|
@@ -1246,7 +1178,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1246
1178
|
this.editValues = {};
|
|
1247
1179
|
this.configCopied = false;
|
|
1248
1180
|
},
|
|
1249
|
-
// Toggle edit mode
|
|
1250
1181
|
toggleEditMode() {
|
|
1251
1182
|
this.editMode = !this.editMode;
|
|
1252
1183
|
if (this.editMode) {
|
|
@@ -1255,30 +1186,37 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1255
1186
|
this.restoreCSSVariables();
|
|
1256
1187
|
}
|
|
1257
1188
|
},
|
|
1258
|
-
// Check if any values have been edited and not yet copied
|
|
1259
1189
|
hasUnsavedEdits() {
|
|
1260
1190
|
return Object.keys(this.editValues).length > 0 && !this.configCopied;
|
|
1261
1191
|
},
|
|
1262
|
-
// Open floating editor
|
|
1263
1192
|
openEditor() {
|
|
1264
1193
|
this.showEditor = true;
|
|
1265
1194
|
this.editMode = true;
|
|
1266
1195
|
this.loadCurrentValues();
|
|
1267
1196
|
localStorage.setItem("breakoutGridEditorOpen", "true");
|
|
1268
1197
|
},
|
|
1269
|
-
// Close floating editor
|
|
1270
1198
|
closeEditor(force = false) {
|
|
1271
1199
|
if (!force && this.hasUnsavedEdits()) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1200
|
+
this.showCloseWarningModal = true;
|
|
1201
|
+
return;
|
|
1275
1202
|
}
|
|
1276
1203
|
this.showEditor = false;
|
|
1277
1204
|
this.editMode = false;
|
|
1278
1205
|
this.restoreCSSVariables();
|
|
1279
1206
|
localStorage.setItem("breakoutGridEditorOpen", "false");
|
|
1280
1207
|
},
|
|
1281
|
-
|
|
1208
|
+
closeWarningCopyAndClose() {
|
|
1209
|
+
this.copyConfig();
|
|
1210
|
+
this.showCloseWarningModal = false;
|
|
1211
|
+
this.closeEditor(true);
|
|
1212
|
+
},
|
|
1213
|
+
closeWarningDiscard() {
|
|
1214
|
+
this.showCloseWarningModal = false;
|
|
1215
|
+
this.closeEditor(true);
|
|
1216
|
+
},
|
|
1217
|
+
closeWarningGoBack() {
|
|
1218
|
+
this.showCloseWarningModal = false;
|
|
1219
|
+
},
|
|
1282
1220
|
_dragConfigs: {
|
|
1283
1221
|
editor: { pos: "editorPos", dragging: "isDragging", offset: "dragOffset", storage: "breakoutGridEditorPos" },
|
|
1284
1222
|
spacing: { pos: "spacingPanelPos", dragging: "isDraggingSpacing", offset: "dragOffsetSpacing", storage: "breakoutGridSpacingPos" }
|
|
@@ -1299,7 +1237,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1299
1237
|
if (this[cfg.dragging]) localStorage.setItem(cfg.storage, JSON.stringify(this[cfg.pos]));
|
|
1300
1238
|
this[cfg.dragging] = false;
|
|
1301
1239
|
},
|
|
1302
|
-
// Editor drag (shorthand)
|
|
1303
1240
|
startDrag(e) {
|
|
1304
1241
|
this.startPanelDrag(e, "editor");
|
|
1305
1242
|
},
|
|
@@ -1309,7 +1246,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1309
1246
|
stopDrag() {
|
|
1310
1247
|
this.stopPanelDrag("editor");
|
|
1311
1248
|
},
|
|
1312
|
-
// Spacing drag (shorthand)
|
|
1313
1249
|
startDragSpacing(e) {
|
|
1314
1250
|
this.startPanelDrag(e, "spacing");
|
|
1315
1251
|
},
|
|
@@ -1319,7 +1255,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1319
1255
|
stopDragSpacing() {
|
|
1320
1256
|
this.stopPanelDrag("spacing");
|
|
1321
1257
|
},
|
|
1322
|
-
// Column resize drag handling
|
|
1323
1258
|
startColumnResize(e, columnType) {
|
|
1324
1259
|
if (!this.editMode) return;
|
|
1325
1260
|
e.preventDefault();
|
|
@@ -1353,18 +1288,14 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1353
1288
|
stopColumnResize() {
|
|
1354
1289
|
this.resizingColumn = null;
|
|
1355
1290
|
},
|
|
1356
|
-
// Map column names to their config keys for resizing
|
|
1357
1291
|
getResizeConfig(colName) {
|
|
1358
1292
|
const map = {
|
|
1359
1293
|
"full-limit": "fullLimit",
|
|
1360
1294
|
"feature": "featureScale",
|
|
1361
1295
|
"popout": "popoutWidth"
|
|
1362
|
-
// content has its own integrated handles for min/max/base
|
|
1363
|
-
// feature has its own integrated handles for min/scale/max
|
|
1364
1296
|
};
|
|
1365
1297
|
return map[colName] || null;
|
|
1366
1298
|
},
|
|
1367
|
-
// Parse a CSS variables string into a config object
|
|
1368
1299
|
parseConfigString(input) {
|
|
1369
1300
|
const str = input.trim();
|
|
1370
1301
|
const config = { gapScale: {}, breakpoints: {} };
|
|
@@ -1412,19 +1343,16 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1412
1343
|
}
|
|
1413
1344
|
return config;
|
|
1414
1345
|
},
|
|
1415
|
-
// Open restore modal
|
|
1416
1346
|
openRestoreModal() {
|
|
1417
1347
|
this.showRestoreModal = true;
|
|
1418
1348
|
this.restoreInput = "";
|
|
1419
1349
|
this.restoreError = null;
|
|
1420
1350
|
},
|
|
1421
|
-
// Close restore modal
|
|
1422
1351
|
closeRestoreModal() {
|
|
1423
1352
|
this.showRestoreModal = false;
|
|
1424
1353
|
this.restoreInput = "";
|
|
1425
1354
|
this.restoreError = null;
|
|
1426
1355
|
},
|
|
1427
|
-
// Apply a parsed config to the editor
|
|
1428
1356
|
restoreConfig() {
|
|
1429
1357
|
this.restoreError = null;
|
|
1430
1358
|
try {
|
|
@@ -1482,7 +1410,7 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1482
1410
|
x-transition:leave="transition ease-in duration-150"
|
|
1483
1411
|
x-transition:leave-start="opacity-100"
|
|
1484
1412
|
x-transition:leave-end="opacity-0"
|
|
1485
|
-
style="position: absolute
|
|
1413
|
+
:style="{ position: 'absolute', inset: 0, background: 'rgba(255, 255, 255, ' + backdropOpacity + ')', zIndex: 1 }"></div>
|
|
1486
1414
|
|
|
1487
1415
|
<!-- Advanced Span Examples Overlay -->
|
|
1488
1416
|
<div x-show="showAdvanced"
|
|
@@ -1752,7 +1680,7 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
1752
1680
|
</div>
|
|
1753
1681
|
|
|
1754
1682
|
<!-- Grid Overlay (hidden in Advanced mode) -->
|
|
1755
|
-
<div x-show="!showAdvanced" x-init="$watch('isVisible', v => v && setTimeout(() => updateColumnWidths(), 50)); setTimeout(() => updateColumnWidths(), 100)" class="grid-cols-breakout breakout-visualizer-grid" style="height: 100
|
|
1683
|
+
<div x-show="!showAdvanced" x-init="$watch('isVisible', v => v && setTimeout(() => updateColumnWidths(), 50)); setTimeout(() => updateColumnWidths(), 100)" class="grid-cols-breakout breakout-visualizer-grid" :style="{ height: '100%', position: 'relative', zIndex: 2, opacity: gridOpacity }">
|
|
1756
1684
|
<template x-for="area in gridAreas" :key="area.name">
|
|
1757
1685
|
<div :class="'col-' + area.name"
|
|
1758
1686
|
@click="selectArea(area.name)"
|
|
@@ -2157,6 +2085,22 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
2157
2085
|
</div>
|
|
2158
2086
|
</div>
|
|
2159
2087
|
|
|
2088
|
+
<!-- Opacity Sliders -->
|
|
2089
|
+
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2090
|
+
<div style="display: flex; flex-direction: column; gap: 6px;">
|
|
2091
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
2092
|
+
<span style="font-size: 9px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; width: 28px; flex-shrink: 0;">Grid</span>
|
|
2093
|
+
<input type="range" x-model="gridOpacity" min="0.1" max="1" step="0.1"
|
|
2094
|
+
style="flex: 1; height: 4px; cursor: pointer; accent-color: #1a1a2e;">
|
|
2095
|
+
</div>
|
|
2096
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
2097
|
+
<span style="font-size: 9px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; width: 28px; flex-shrink: 0;">Page</span>
|
|
2098
|
+
<input type="range" x-model="backdropOpacity" min="0" max="1" step="0.05"
|
|
2099
|
+
style="flex: 1; height: 4px; cursor: pointer; accent-color: #1a1a2e;">
|
|
2100
|
+
</div>
|
|
2101
|
+
</div>
|
|
2102
|
+
</div>
|
|
2103
|
+
|
|
2160
2104
|
<!-- Padding Options -->
|
|
2161
2105
|
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2162
2106
|
<div style="font-size: 9px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px;">Padding</div>
|
|
@@ -2237,6 +2181,23 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
2237
2181
|
<span style="font-weight: 600;">⚠️</span> <span x-text="getTrackOverflowWarning()"></span>
|
|
2238
2182
|
</div>
|
|
2239
2183
|
|
|
2184
|
+
<!-- Default Column Section -->
|
|
2185
|
+
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2186
|
+
<div style="display: flex; align-items: center; justify-content: space-between;">
|
|
2187
|
+
<div @click="copySection('defaultCol')" style="cursor: pointer;">
|
|
2188
|
+
<div style="font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;" :style="{ color: sectionCopied === 'defaultCol' ? '#10b981' : '#6b7280' }" x-text="sectionCopied === 'defaultCol' ? '✓ Copied' : 'Default Column'"></div>
|
|
2189
|
+
<div style="font-size: 9px; color: #9ca3af; margin-top: 2px;">For children without col-* class</div>
|
|
2190
|
+
</div>
|
|
2191
|
+
<select @change="editValues.defaultCol = $event.target.value; configCopied = false"
|
|
2192
|
+
:value="editValues.defaultCol || configOptions.defaultCol.value"
|
|
2193
|
+
style="padding: 6px 8px; font-size: 11px; border: 1px solid #e5e5e5; border-radius: 4px; background: #f9fafb; cursor: pointer;">
|
|
2194
|
+
<template x-for="opt in configOptions.defaultCol.options" :key="opt">
|
|
2195
|
+
<option :value="opt" :selected="(editValues.defaultCol || configOptions.defaultCol.value) === opt" x-text="opt"></option>
|
|
2196
|
+
</template>
|
|
2197
|
+
</select>
|
|
2198
|
+
</div>
|
|
2199
|
+
</div>
|
|
2200
|
+
|
|
2240
2201
|
<!-- Content Section -->
|
|
2241
2202
|
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2242
2203
|
<div @click="copySection('content')" style="font-size: 9px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; cursor: pointer; display: flex; align-items: center; gap: 6px;" :style="{ color: sectionCopied === 'content' ? '#10b981' : '#6b7280' }">
|
|
@@ -2282,23 +2243,6 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
2282
2243
|
</div>
|
|
2283
2244
|
</div>
|
|
2284
2245
|
|
|
2285
|
-
<!-- Default Column Section -->
|
|
2286
|
-
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2287
|
-
<div style="display: flex; align-items: center; justify-content: space-between;">
|
|
2288
|
-
<div @click="copySection('defaultCol')" style="cursor: pointer;">
|
|
2289
|
-
<div style="font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;" :style="{ color: sectionCopied === 'defaultCol' ? '#10b981' : '#6b7280' }" x-text="sectionCopied === 'defaultCol' ? '✓ Copied' : 'Default Column'"></div>
|
|
2290
|
-
<div style="font-size: 9px; color: #9ca3af; margin-top: 2px;">For children without col-* class</div>
|
|
2291
|
-
</div>
|
|
2292
|
-
<select @change="editValues.defaultCol = $event.target.value; configCopied = false"
|
|
2293
|
-
:value="editValues.defaultCol || configOptions.defaultCol.value"
|
|
2294
|
-
style="padding: 6px 8px; font-size: 11px; border: 1px solid #e5e5e5; border-radius: 4px; background: #f9fafb; cursor: pointer;">
|
|
2295
|
-
<template x-for="opt in configOptions.defaultCol.options" :key="opt">
|
|
2296
|
-
<option :value="opt" :selected="(editValues.defaultCol || configOptions.defaultCol.value) === opt" x-text="opt"></option>
|
|
2297
|
-
</template>
|
|
2298
|
-
</select>
|
|
2299
|
-
</div>
|
|
2300
|
-
</div>
|
|
2301
|
-
|
|
2302
2246
|
<!-- Track Widths Section -->
|
|
2303
2247
|
<div style="padding: 8px 12px; background: white; border-bottom: 1px solid #e5e5e5;">
|
|
2304
2248
|
<div @click="copySection('tracks')" style="font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; cursor: pointer;" :style="{ color: sectionCopied === 'tracks' ? '#10b981' : '#6b7280' }" x-text="sectionCopied === 'tracks' ? '✓ Copied' : 'Track Widths'"></div>
|
|
@@ -2490,6 +2434,53 @@ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
|
|
|
2490
2434
|
</div>
|
|
2491
2435
|
</div>
|
|
2492
2436
|
|
|
2437
|
+
<!-- Close Warning Modal -->
|
|
2438
|
+
<div x-show="showCloseWarningModal"
|
|
2439
|
+
x-transition:enter="transition ease-out duration-200"
|
|
2440
|
+
x-transition:enter-start="opacity-0"
|
|
2441
|
+
x-transition:enter-end="opacity-100"
|
|
2442
|
+
x-transition:leave="transition ease-in duration-150"
|
|
2443
|
+
x-transition:leave-start="opacity-100"
|
|
2444
|
+
x-transition:leave-end="opacity-0"
|
|
2445
|
+
style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 10003; pointer-events: auto;">
|
|
2446
|
+
<div @click.stop style="background: white; border-radius: 8px; box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); width: 420px; max-width: 90vw; font-family: system-ui, -apple-system, sans-serif;">
|
|
2447
|
+
<!-- Modal Header -->
|
|
2448
|
+
<div style="padding: 12px 16px; background: #fef3c7; color: #92400e; border-radius: 8px 8px 0 0; display: flex; align-items: center; gap: 10px;">
|
|
2449
|
+
<svg style="width: 20px; height: 20px; flex-shrink: 0;" fill="currentColor" viewBox="0 0 20 20">
|
|
2450
|
+
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
|
|
2451
|
+
</svg>
|
|
2452
|
+
<span style="font-weight: 600; font-size: 14px;">Unsaved Configuration</span>
|
|
2453
|
+
</div>
|
|
2454
|
+
<!-- Modal Body -->
|
|
2455
|
+
<div style="padding: 16px;">
|
|
2456
|
+
<p style="font-size: 13px; color: #374151; margin: 0 0 12px 0; line-height: 1.5;">
|
|
2457
|
+
Your grid configuration changes are stored in <strong>browser localStorage</strong> and will only apply while the visualizer is loaded.
|
|
2458
|
+
</p>
|
|
2459
|
+
<div style="background: #f3f4f6; border-radius: 6px; padding: 12px; margin-bottom: 12px;">
|
|
2460
|
+
<p style="font-size: 12px; color: #4b5563; margin: 0 0 8px 0; line-height: 1.5;">
|
|
2461
|
+
<strong>To make changes permanent:</strong>
|
|
2462
|
+
</p>
|
|
2463
|
+
<ol style="font-size: 11px; color: #6b7280; margin: 0; padding-left: 16px; line-height: 1.6;">
|
|
2464
|
+
<li>Copy the config to your clipboard</li>
|
|
2465
|
+
<li>Paste into your project's CSS file</li>
|
|
2466
|
+
<li>Remove the visualizer script from production</li>
|
|
2467
|
+
</ol>
|
|
2468
|
+
</div>
|
|
2469
|
+
<p style="font-size: 11px; color: #9ca3af; margin: 0; line-height: 1.4;">
|
|
2470
|
+
Without copying, your changes will be lost when the visualizer is removed.
|
|
2471
|
+
</p>
|
|
2472
|
+
</div>
|
|
2473
|
+
<!-- Modal Footer -->
|
|
2474
|
+
<div style="padding: 12px 16px; background: #f7f7f7; border-radius: 0 0 8px 8px; display: flex; justify-content: space-between; gap: 8px;">
|
|
2475
|
+
<button @click="closeWarningDiscard()" style="padding: 8px 16px; font-size: 11px; font-weight: 600; border: 1px solid #fca5a5; border-radius: 4px; cursor: pointer; background: #fef2f2; color: #dc2626;">Discard Changes</button>
|
|
2476
|
+
<div style="display: flex; gap: 8px;">
|
|
2477
|
+
<button @click="closeWarningGoBack()" style="padding: 8px 16px; font-size: 11px; font-weight: 600; border: 1px solid #e5e5e5; border-radius: 4px; cursor: pointer; background: white; color: #374151;">Go Back</button>
|
|
2478
|
+
<button @click="closeWarningCopyAndClose()" style="padding: 8px 16px; font-size: 11px; font-weight: 600; border: none; border-radius: 4px; cursor: pointer; background: #1a1a2e; color: white;">Copy & Close</button>
|
|
2479
|
+
</div>
|
|
2480
|
+
</div>
|
|
2481
|
+
</div>
|
|
2482
|
+
</div>
|
|
2483
|
+
|
|
2493
2484
|
<!-- Grid Diagram -->
|
|
2494
2485
|
<div x-show="showDiagram"
|
|
2495
2486
|
style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border-radius: 0.5rem; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); pointer-events: auto; z-index: 10001; padding: 1.5rem; max-width: 90vw;">
|