inline-style-editor 1.4.3 → 1.5.4
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/README.md +5 -2
- package/dist/inline-style-editor.css +1 -1
- package/dist/inline-style-editor.js +3 -2
- package/dist/inline-style-editor.js.map +1 -1
- package/dist/inline-style-editor.mjs +394 -249
- package/dist/inline-style-editor.mjs.map +1 -1
- package/package.json +1 -1
- package/src/assets/style.scss +123 -30
- package/src/components/InlineStyleEditor.svelte +160 -66
package/package.json
CHANGED
package/src/assets/style.scss
CHANGED
|
@@ -38,21 +38,13 @@
|
|
|
38
38
|
margin: auto;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
margin-left: 4px;
|
|
47
|
-
}
|
|
41
|
+
.current-value {
|
|
42
|
+
font-size: 12px;
|
|
43
|
+
color: #64748b;
|
|
44
|
+
min-width: 40px;
|
|
45
|
+
text-align: right;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
.delete {
|
|
51
|
-
cursor: pointer;
|
|
52
|
-
font-size: 20px;
|
|
53
|
-
margin: 0 4px;
|
|
54
|
-
margin-bottom: 2px;
|
|
55
|
-
}
|
|
56
48
|
|
|
57
49
|
.select-tab {
|
|
58
50
|
display: flex;
|
|
@@ -91,21 +83,100 @@
|
|
|
91
83
|
}
|
|
92
84
|
|
|
93
85
|
.editor .prop-section {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
86
|
+
background: #f8fafc;
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
padding: 8px;
|
|
89
|
+
margin: 6px 0;
|
|
90
|
+
|
|
91
|
+
&:first-child {
|
|
92
|
+
margin-top: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&.slider {
|
|
96
|
+
.prop-header + input[type="range"] {
|
|
97
|
+
display: inline-block;
|
|
98
|
+
width: calc(100% - 50px);
|
|
99
|
+
vertical-align: middle;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.current-value {
|
|
103
|
+
display: inline-block;
|
|
104
|
+
vertical-align: middle;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
98
107
|
}
|
|
99
108
|
|
|
100
|
-
.
|
|
101
|
-
|
|
109
|
+
.prop-header {
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: space-between;
|
|
113
|
+
margin-bottom: 6px;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
.
|
|
116
|
+
.prop-name {
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 8px;
|
|
105
120
|
color: #5d5d5d;
|
|
106
121
|
font-weight: bold;
|
|
107
122
|
}
|
|
108
123
|
|
|
124
|
+
.selected-label {
|
|
125
|
+
font-size: 12px;
|
|
126
|
+
color: #64748b;
|
|
127
|
+
font-weight: 500;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.close-button,
|
|
131
|
+
.delete-btn {
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
justify-content: center;
|
|
135
|
+
width: 20px;
|
|
136
|
+
height: 20px;
|
|
137
|
+
padding: 0;
|
|
138
|
+
border: none;
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
flex-shrink: 0;
|
|
141
|
+
transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
|
|
142
|
+
|
|
143
|
+
svg {
|
|
144
|
+
width: 12px;
|
|
145
|
+
height: 12px;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.delete-btn {
|
|
150
|
+
border-radius: 4px;
|
|
151
|
+
background: transparent;
|
|
152
|
+
color: #94a3b8;
|
|
153
|
+
|
|
154
|
+
&:hover {
|
|
155
|
+
background: #fee2e2;
|
|
156
|
+
color: #dc2626;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.close-button {
|
|
161
|
+
position: absolute;
|
|
162
|
+
top: -8px;
|
|
163
|
+
right: -8px;
|
|
164
|
+
border-radius: 50%;
|
|
165
|
+
background: #64748b;
|
|
166
|
+
color: white;
|
|
167
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
168
|
+
|
|
169
|
+
&:hover {
|
|
170
|
+
background: #475569;
|
|
171
|
+
transform: scale(1.1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
svg {
|
|
175
|
+
width: 10px;
|
|
176
|
+
height: 10px;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
109
180
|
.editor .btn {
|
|
110
181
|
&.active {
|
|
111
182
|
background-color: #4d84bf;
|
|
@@ -125,19 +196,41 @@
|
|
|
125
196
|
padding: 5px;
|
|
126
197
|
}
|
|
127
198
|
|
|
128
|
-
.
|
|
129
|
-
position: absolute;
|
|
130
|
-
top: -7px;
|
|
131
|
-
right: -7px;
|
|
132
|
-
background-color: #dbdbdb;
|
|
133
|
-
color: #818181;
|
|
134
|
-
width: 15px;
|
|
135
|
-
height: 15px;
|
|
199
|
+
.icon-selector {
|
|
136
200
|
display: flex;
|
|
137
|
-
|
|
201
|
+
gap: 2px;
|
|
138
202
|
align-items: center;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.icon-btn {
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
justify-content: center;
|
|
209
|
+
width: 26px;
|
|
210
|
+
height: 26px;
|
|
211
|
+
padding: 4px;
|
|
212
|
+
border: 1.5px solid transparent;
|
|
213
|
+
border-radius: 5px;
|
|
214
|
+
background: transparent;
|
|
139
215
|
cursor: pointer;
|
|
140
|
-
|
|
216
|
+
color: #94a3b8;
|
|
217
|
+
|
|
218
|
+
&:hover {
|
|
219
|
+
background: #e2e8f0;
|
|
220
|
+
color: #475569;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
&.selected {
|
|
224
|
+
background: white;
|
|
225
|
+
border-color: #3b82f6;
|
|
226
|
+
color: #2563eb;
|
|
227
|
+
box-shadow: 0 1px 3px 0 rgba(59, 130, 246, 0.3), 0 0 0 1px rgba(59, 130, 246, 0.1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
svg {
|
|
231
|
+
width: 16px;
|
|
232
|
+
height: 16px;
|
|
233
|
+
}
|
|
141
234
|
}
|
|
142
235
|
|
|
143
236
|
.layout_default.picker_wrapper {
|
|
@@ -56,6 +56,23 @@
|
|
|
56
56
|
"background-color": { type: "color" },
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
const propertyIcons = {
|
|
60
|
+
stroke: `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="2" y1="14" x2="14" y2="2"/></svg>`,
|
|
61
|
+
fill: `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="2" y="2" width="12" height="12" rx="2"/></svg>`,
|
|
62
|
+
color: `<svg viewBox="0 0 16 16" fill="currentColor"><text x="3" y="11" font-size="10" font-weight="bold">A</text><rect x="2" y="13" width="12" height="2"/></svg>`,
|
|
63
|
+
"border-color": `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="12" height="12" rx="1"/></svg>`,
|
|
64
|
+
"background-color": `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="4" y="4" width="10" height="10" rx="1" opacity="0.5"/><rect x="2" y="2" width="10" height="10" rx="1"/></svg>`,
|
|
65
|
+
"border-radius": `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 10 L2 2 L10 2" stroke-linecap="round"/><path d="M2 10 Q2 14 6 14 L14 14" stroke-linecap="round"/></svg>`,
|
|
66
|
+
"border-width": `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="2" y="2" width="12" height="2"/><rect x="2" y="7" width="12" height="3"/><rect x="2" y="13" width="12" height="1"/></svg>`,
|
|
67
|
+
"border-style": `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="2" y="2" width="12" height="1.5"/><rect x="2" y="7" width="3" height="1.5"/><rect x="7" y="7" width="3" height="1.5"/><rect x="2" y="12" width="1.5" height="1.5"/><rect x="5" y="12" width="1.5" height="1.5"/><rect x="8" y="12" width="1.5" height="1.5"/><rect x="11" y="12" width="1.5" height="1.5"/></svg>`,
|
|
68
|
+
"font-size": `<svg viewBox="0 0 16 16" fill="currentColor"><text x="1" y="12" font-size="12" font-weight="bold">T</text><text x="9" y="12" font-size="8" font-weight="bold">T</text></svg>`,
|
|
69
|
+
"font-weight": `<svg viewBox="0 0 16 16" fill="currentColor"><text x="3" y="13" font-size="14" font-weight="bold">B</text></svg>`,
|
|
70
|
+
"font-family": `<svg viewBox="0 0 16 16" fill="currentColor"><text x="4" y="13" font-size="14" font-style="italic" font-family="serif">F</text></svg>`,
|
|
71
|
+
"stroke-width": `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="2" y="2" width="12" height="2"/><rect x="2" y="7" width="12" height="3"/><rect x="2" y="13" width="12" height="1"/></svg>`,
|
|
72
|
+
"stroke-dasharray": `<svg viewBox="0 0 16 16" fill="currentColor"><rect x="1" y="7" width="4" height="2"/><rect x="7" y="7" width="4" height="2"/><rect x="13" y="7" width="2" height="2"/></svg>`,
|
|
73
|
+
"stroke-linejoin": `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"><polyline points="3,12 8,4 13,12"/></svg>`,
|
|
74
|
+
};
|
|
75
|
+
|
|
59
76
|
// Props
|
|
60
77
|
const props = $props();
|
|
61
78
|
const getElems = props.getElems ?? null;
|
|
@@ -70,6 +87,7 @@
|
|
|
70
87
|
if (cssRuleName === "inline") return "Selected element";
|
|
71
88
|
return cssRuleName;
|
|
72
89
|
});
|
|
90
|
+
const ignoredProps = props.ignoredProps ?? [];
|
|
73
91
|
|
|
74
92
|
const typeText = "text";
|
|
75
93
|
const typeBorder = "border";
|
|
@@ -154,6 +172,7 @@
|
|
|
154
172
|
function initAndGroup() {
|
|
155
173
|
const allProps = { ...cssPropByType, ...customProps };
|
|
156
174
|
const _allCurrentPropDefs = pick(allProps, propByType[curType]);
|
|
175
|
+
ignoredProps.forEach((prop) => delete _allCurrentPropDefs[prop]);
|
|
157
176
|
Object.keys(_allCurrentPropDefs).forEach((key) => {
|
|
158
177
|
const propSelectType = _allCurrentPropDefs[key].type;
|
|
159
178
|
let retrieveType = "number";
|
|
@@ -170,10 +189,18 @@
|
|
|
170
189
|
} else {
|
|
171
190
|
_allCurrentPropDefs[key].displayed = getComputedPropValue(currentElement, key, "raw");
|
|
172
191
|
_allCurrentPropDefs[key].value = getComputedPropValue(currentElement, key, retrieveType);
|
|
192
|
+
// Special handling for SVG fill with url() expressions (e.g., gradients)
|
|
193
|
+
if (key === "fill") {
|
|
194
|
+
const rawFill = currentElement.getAttribute?.("fill") || _allCurrentPropDefs[key].displayed;
|
|
195
|
+
if (rawFill && rawFill.includes("url(")) {
|
|
196
|
+
_allCurrentPropDefs[key].originalUrl = rawFill;
|
|
197
|
+
_allCurrentPropDefs[key].value = "#00000000";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
173
200
|
}
|
|
174
201
|
});
|
|
175
|
-
|
|
176
|
-
|
|
202
|
+
console.log(_allCurrentPropDefs);
|
|
203
|
+
const _propsByType = Object.entries(_allCurrentPropDefs)
|
|
177
204
|
.reduce((byType, [propName, selectorDef]) => {
|
|
178
205
|
const selectorType = selectorDef.type;
|
|
179
206
|
const existing = byType.find((x) => x.type === selectorType);
|
|
@@ -191,6 +218,18 @@
|
|
|
191
218
|
if (inputTypeOrder[a.type] > inputTypeOrder[b.type]) return 1;
|
|
192
219
|
return 0;
|
|
193
220
|
});
|
|
221
|
+
|
|
222
|
+
// Pre-select fill over stroke if the element has a non-transparent fill
|
|
223
|
+
const colorGroup = _propsByType.find((g) => g.type === "color");
|
|
224
|
+
if (colorGroup) {
|
|
225
|
+
const fillIndex = colorGroup.props.indexOf("fill");
|
|
226
|
+
const fillValue = _allCurrentPropDefs["fill"]?.value;
|
|
227
|
+
if (fillIndex !== -1 && fillValue && fillValue !== "#00000000") {
|
|
228
|
+
colorGroup.selected = fillIndex;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
propsByType = _propsByType;
|
|
194
233
|
allCurrentPropDefs = _allCurrentPropDefs;
|
|
195
234
|
updateHelpers();
|
|
196
235
|
}
|
|
@@ -448,13 +487,48 @@
|
|
|
448
487
|
close();
|
|
449
488
|
}
|
|
450
489
|
function deleteProp(propName) {
|
|
451
|
-
|
|
452
|
-
|
|
490
|
+
const propDef = allCurrentPropDefs[propName];
|
|
491
|
+
const isCustomProp = propName in customProps;
|
|
492
|
+
|
|
493
|
+
// Check if custom prop has a defaultValue
|
|
494
|
+
if (isCustomProp && propDef && "defaultValue" in customProps[propName]) {
|
|
495
|
+
const defaultValue = customProps[propName].defaultValue;
|
|
496
|
+
if (propDef.setter) {
|
|
497
|
+
propDef.setter(currentElement, defaultValue);
|
|
498
|
+
}
|
|
499
|
+
propDef.value = defaultValue;
|
|
500
|
+
propDef.displayed = defaultValue;
|
|
501
|
+
onStyleChanged(currentElement, currentRule, propName, defaultValue);
|
|
502
|
+
} else if (propName === "fill" && propDef?.originalUrl) {
|
|
503
|
+
// Restore original url() expression for SVG fill
|
|
504
|
+
const urlValue = propDef.originalUrl;
|
|
505
|
+
if (currentRule === "inline") {
|
|
506
|
+
currentElement.style.fill = urlValue;
|
|
507
|
+
} else {
|
|
508
|
+
currentRule.style.setProperty("fill", urlValue);
|
|
509
|
+
}
|
|
510
|
+
propDef.value = "#00000000";
|
|
511
|
+
propDef.displayed = urlValue;
|
|
512
|
+
onStyleChanged(currentElement, currentRule, "fill", urlValue);
|
|
453
513
|
} else {
|
|
454
|
-
|
|
514
|
+
// Standard CSS property reset
|
|
515
|
+
if (currentRule === "inline") {
|
|
516
|
+
currentElement.style.removeProperty(propName);
|
|
517
|
+
} else {
|
|
518
|
+
currentRule.style.removeProperty(propName);
|
|
519
|
+
}
|
|
520
|
+
onStyleChanged(currentElement, currentRule, propName, null);
|
|
521
|
+
// Update the displayed value without rebuilding (which would reset selection)
|
|
522
|
+
if (propDef) {
|
|
523
|
+
const propSelectType = propDef.type;
|
|
524
|
+
let retrieveType = "number";
|
|
525
|
+
if (propSelectType === "color") retrieveType = "rgb";
|
|
526
|
+
else if (propSelectType === "select") retrieveType = "raw";
|
|
527
|
+
propDef.displayed = getComputedPropValue(currentElement, propName, "raw");
|
|
528
|
+
propDef.value = getComputedPropValue(currentElement, propName, retrieveType);
|
|
529
|
+
}
|
|
455
530
|
}
|
|
456
|
-
|
|
457
|
-
initAndGroup();
|
|
531
|
+
updateHelpers();
|
|
458
532
|
}
|
|
459
533
|
|
|
460
534
|
function selectRule(ruleIndex) {
|
|
@@ -484,7 +558,11 @@
|
|
|
484
558
|
</svg>
|
|
485
559
|
|
|
486
560
|
<div class="ise" bind:this={self}>
|
|
487
|
-
<
|
|
561
|
+
<button class="close-button" title="Close" onclick={close}>
|
|
562
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.5">
|
|
563
|
+
<path d="M4 4 L12 12 M12 4 L4 12" />
|
|
564
|
+
</svg>
|
|
565
|
+
</button>
|
|
488
566
|
{#if targetsToSearch.length > 1}
|
|
489
567
|
<div class="select-tab">
|
|
490
568
|
<b> Element </b>
|
|
@@ -501,73 +579,89 @@
|
|
|
501
579
|
{/each}
|
|
502
580
|
</div>
|
|
503
581
|
{/if}
|
|
504
|
-
|
|
505
|
-
<
|
|
506
|
-
|
|
507
|
-
|
|
582
|
+
{#if allRules[selectedElemIndex]?.length > 1}
|
|
583
|
+
<div class="select-tab">
|
|
584
|
+
<b> Applied to: </b>
|
|
585
|
+
{#if nbChars(getRuleNamesTransformed(allRules[selectedElemIndex])) > 30}
|
|
586
|
+
<select onchange={(e) => selectRule(e.target.value)}>
|
|
587
|
+
{#each getRuleNames(allRules[selectedElemIndex]) as ruleName, ruleIndex}
|
|
588
|
+
<option selected={selectedRuleIndex === ruleIndex} value={ruleIndex}
|
|
589
|
+
>{getCssRuleName(ruleName, clickedElement)}</option
|
|
590
|
+
>
|
|
591
|
+
{/each}
|
|
592
|
+
</select>
|
|
593
|
+
{:else}
|
|
508
594
|
{#each getRuleNames(allRules[selectedElemIndex]) as ruleName, ruleIndex}
|
|
509
|
-
<
|
|
510
|
-
|
|
595
|
+
<span
|
|
596
|
+
title={ruleName}
|
|
597
|
+
class:selected={selectedRuleIndex === ruleIndex}
|
|
598
|
+
onclick={() => {
|
|
599
|
+
selectRule(ruleIndex);
|
|
600
|
+
}}
|
|
601
|
+
>
|
|
602
|
+
{getCssRuleName(ruleName, clickedElement)}</span
|
|
511
603
|
>
|
|
512
604
|
{/each}
|
|
513
|
-
</select>
|
|
514
|
-
{:else}
|
|
515
|
-
{#each getRuleNames(allRules[selectedElemIndex]) as ruleName, ruleIndex}
|
|
516
|
-
<span
|
|
517
|
-
title={ruleName}
|
|
518
|
-
class:selected={selectedRuleIndex === ruleIndex}
|
|
519
|
-
onclick={() => {
|
|
520
|
-
selectRule(ruleIndex);
|
|
521
|
-
}}
|
|
522
|
-
>
|
|
523
|
-
{getCssRuleName(ruleName, clickedElement)}</span
|
|
524
|
-
>
|
|
525
|
-
{/each}
|
|
526
|
-
{/if}
|
|
527
|
-
</div>
|
|
528
|
-
<div class="select-tab">
|
|
529
|
-
<b> Property type: </b>
|
|
530
|
-
{#each allTypes[selectedElemIndex] || [] as type, typeIndex}
|
|
531
|
-
<!-- Only display "custom" on "inline" rule -->
|
|
532
|
-
{#if type !== "custom" || (currentRule === "inline" && type === "custom" && hasDisplayedCustom)}
|
|
533
|
-
<span
|
|
534
|
-
class:selected={selectedTypeIndex === typeIndex}
|
|
535
|
-
onclick={() => {
|
|
536
|
-
selectedTypeIndex = typeIndex;
|
|
537
|
-
}}
|
|
538
|
-
>
|
|
539
|
-
{type === "stroke" ? "SVG paint" : capitalizeFirstLetter(type)}
|
|
540
|
-
</span>
|
|
541
605
|
{/if}
|
|
542
|
-
|
|
543
|
-
|
|
606
|
+
</div>
|
|
607
|
+
{/if}
|
|
608
|
+
{#if (allTypes[selectedElemIndex] || []).filter((t) => t !== "custom" || (currentRule === "inline" && hasDisplayedCustom)).length > 1}
|
|
609
|
+
<div class="select-tab">
|
|
610
|
+
<b> Property type: </b>
|
|
611
|
+
{#each allTypes[selectedElemIndex] || [] as type, typeIndex}
|
|
612
|
+
<!-- Only display "custom" on "inline" rule -->
|
|
613
|
+
{#if type !== "custom" || (currentRule === "inline" && type === "custom" && hasDisplayedCustom)}
|
|
614
|
+
<span
|
|
615
|
+
class:selected={selectedTypeIndex === typeIndex}
|
|
616
|
+
onclick={() => {
|
|
617
|
+
selectedTypeIndex = typeIndex;
|
|
618
|
+
}}
|
|
619
|
+
>
|
|
620
|
+
{type === "stroke" ? "SVG paint" : capitalizeFirstLetter(type)}
|
|
621
|
+
</span>
|
|
622
|
+
{/if}
|
|
623
|
+
{/each}
|
|
624
|
+
</div>
|
|
625
|
+
{/if}
|
|
544
626
|
{#if allTypes[selectedElemIndex]}
|
|
545
627
|
<div class="editor">
|
|
546
628
|
{#each propsByType as choices}
|
|
547
629
|
{@const selectedName = choices.props[choices.selected]}
|
|
548
630
|
<div class="prop-section {choices.type}">
|
|
549
|
-
<div class="prop-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
choices.
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
{
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
631
|
+
<div class="prop-header">
|
|
632
|
+
<div class="prop-name">
|
|
633
|
+
{#if choices.props.length > 1}
|
|
634
|
+
<div class="icon-selector">
|
|
635
|
+
{#each choices.props as propName, i}
|
|
636
|
+
<button
|
|
637
|
+
class="icon-btn"
|
|
638
|
+
class:selected={i === choices.selected}
|
|
639
|
+
title={choices.type === "color"
|
|
640
|
+
? `${capitalizeFirstLetter(propName)} color`
|
|
641
|
+
: pascalCaseToSentence(propName)}
|
|
642
|
+
onclick={async () => {
|
|
643
|
+
choices.selected = i;
|
|
644
|
+
await tick();
|
|
645
|
+
}}
|
|
646
|
+
>
|
|
647
|
+
{@html propertyIcons[propName]}
|
|
648
|
+
</button>
|
|
649
|
+
{/each}
|
|
650
|
+
</div>
|
|
651
|
+
<span class="selected-label"
|
|
652
|
+
>{choices.type === "color"
|
|
653
|
+
? `${capitalizeFirstLetter(selectedName)} color`
|
|
654
|
+
: pascalCaseToSentence(selectedName)}</span
|
|
655
|
+
>
|
|
656
|
+
{:else}
|
|
657
|
+
<span>{pascalCaseToSentence(selectedName)}</span>
|
|
658
|
+
{/if}
|
|
659
|
+
</div>
|
|
660
|
+
<button class="delete-btn" title="Reset to default" onclick={() => deleteProp(selectedName)}>
|
|
661
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2">
|
|
662
|
+
<path d="M4 4 L12 12 M12 4 L4 12" />
|
|
663
|
+
</svg>
|
|
664
|
+
</button>
|
|
571
665
|
</div>
|
|
572
666
|
{#if choices.type === "slider"}
|
|
573
667
|
<input
|