camox 0.7.2 → 0.7.3
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/dist/features/vite/vite.js +1 -1
- package/dist/studio-overlays.css +195 -0
- package/package.json +5 -5
|
@@ -59,7 +59,7 @@ function camox(options) {
|
|
|
59
59
|
return `export default "/@fs/${cssPath}";`;
|
|
60
60
|
}
|
|
61
61
|
if (id === RESOLVED_VIRTUAL_OVERLAY_CSS) {
|
|
62
|
-
const css = readFileSync(resolve(sdkRoot, "
|
|
62
|
+
const css = readFileSync(resolve(sdkRoot, "dist/studio-overlays.css"), "utf-8");
|
|
63
63
|
return `export default ${JSON.stringify(css)};`;
|
|
64
64
|
}
|
|
65
65
|
},
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Visual editing overlay styles injected into the preview iframe.
|
|
3
|
+
*
|
|
4
|
+
* State is driven by data attributes on the elements:
|
|
5
|
+
* - data-camox-hovered: element is hovered
|
|
6
|
+
* - data-camox-focused: element is focused/selected
|
|
7
|
+
* - data-camox-overlay-mode="layout": use layout (purple) colors
|
|
8
|
+
*
|
|
9
|
+
* Elements are targeted via their existing data attributes:
|
|
10
|
+
* - [data-camox-field-id]: Field, Link, Image, Embed
|
|
11
|
+
* - [data-camox-block-id]: BlockComponent, Detached
|
|
12
|
+
* - [data-camox-repeater-item-id]: RepeaterItemWrapper
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
--camox-overlay-color-hover: #f472b6bf; /* pink-400 at 75% */
|
|
17
|
+
--camox-overlay-color-selected: #f472b6; /* pink-400 */
|
|
18
|
+
--camox-overlay-layout-color-hover: #c084fcbf; /* purple-400 at 75% */
|
|
19
|
+
--camox-overlay-layout-color-selected: #c084fc; /* purple-400 */
|
|
20
|
+
--camox-overlay-width-hover: 3px;
|
|
21
|
+
--camox-overlay-width-selected: 1px;
|
|
22
|
+
--camox-overlay-inset-field-hover: -1px;
|
|
23
|
+
--camox-overlay-inset-field-selected: -2px;
|
|
24
|
+
--camox-overlay-inset-block-hover: -1px;
|
|
25
|
+
--camox-overlay-inset-block-selected: 0px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Position context for field-level and repeater elements.
|
|
29
|
+
BlockComponent already has position: relative inline.
|
|
30
|
+
Detached wraps user elements (e.g. fixed navbars) so must NOT get position: relative. */
|
|
31
|
+
[data-camox-field-id],
|
|
32
|
+
[data-camox-repeater-item-id] {
|
|
33
|
+
position: relative;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ---- Hovered state ---- */
|
|
37
|
+
|
|
38
|
+
[data-camox-field-id][data-camox-hovered]::after,
|
|
39
|
+
[data-camox-block-id][data-camox-hovered]:not([data-camox-detached])::after,
|
|
40
|
+
[data-camox-repeater-item-id][data-camox-hovered]::after {
|
|
41
|
+
content: "";
|
|
42
|
+
position: absolute;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
z-index: 10;
|
|
45
|
+
inset: var(--camox-overlay-inset-block-hover);
|
|
46
|
+
border: var(--camox-overlay-width-hover) solid var(--camox-overlay-color-hover);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Field-level elements use field-specific inset */
|
|
50
|
+
[data-camox-field-id][data-camox-hovered]:not([data-camox-field-type])::after {
|
|
51
|
+
inset: var(--camox-overlay-inset-field-hover);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ---- Focused state (overrides hovered via source order) ---- */
|
|
55
|
+
|
|
56
|
+
[data-camox-field-id][data-camox-focused]::after,
|
|
57
|
+
[data-camox-block-id][data-camox-focused]:not([data-camox-detached])::after {
|
|
58
|
+
content: "";
|
|
59
|
+
position: absolute;
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
z-index: 10;
|
|
62
|
+
inset: var(--camox-overlay-inset-block-selected);
|
|
63
|
+
border: var(--camox-overlay-width-selected) solid var(--camox-overlay-color-selected);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Field-level elements use field-specific inset */
|
|
67
|
+
[data-camox-field-id][data-camox-focused]:not([data-camox-field-type])::after {
|
|
68
|
+
inset: var(--camox-overlay-inset-field-selected);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ---- Layout mode color overrides ---- */
|
|
72
|
+
|
|
73
|
+
[data-camox-field-id][data-camox-overlay-mode="layout"][data-camox-hovered]::after,
|
|
74
|
+
[data-camox-block-id][data-camox-overlay-mode="layout"][data-camox-hovered]:not(
|
|
75
|
+
[data-camox-detached]
|
|
76
|
+
)::after,
|
|
77
|
+
[data-camox-repeater-item-id][data-camox-overlay-mode="layout"][data-camox-hovered]::after {
|
|
78
|
+
border-color: var(--camox-overlay-layout-color-hover);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[data-camox-field-id][data-camox-overlay-mode="layout"][data-camox-focused]::after,
|
|
82
|
+
[data-camox-block-id][data-camox-overlay-mode="layout"][data-camox-focused]:not(
|
|
83
|
+
[data-camox-detached]
|
|
84
|
+
)::after {
|
|
85
|
+
border-color: var(--camox-overlay-layout-color-selected);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* ---- Embed: z-index above click-interceptor ---- */
|
|
89
|
+
|
|
90
|
+
[data-camox-field-type="embed"][data-camox-hovered]::after,
|
|
91
|
+
[data-camox-field-type="embed"][data-camox-focused]::after {
|
|
92
|
+
z-index: 11;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* ---- Detached: styled directly (not ::after) because the parent element
|
|
96
|
+
(e.g. fixed navbar) must not get position: relative ---- */
|
|
97
|
+
|
|
98
|
+
[data-camox-detached][data-camox-hovered] {
|
|
99
|
+
inset: var(--camox-overlay-inset-block-hover);
|
|
100
|
+
border: var(--camox-overlay-width-hover) solid var(--camox-overlay-color-hover);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
[data-camox-detached][data-camox-focused] {
|
|
104
|
+
inset: var(--camox-overlay-inset-block-selected);
|
|
105
|
+
border: var(--camox-overlay-width-selected) solid var(--camox-overlay-color-selected);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
[data-camox-detached][data-camox-overlay-mode="layout"][data-camox-hovered] {
|
|
109
|
+
border-color: var(--camox-overlay-layout-color-hover);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
[data-camox-detached][data-camox-overlay-mode="layout"][data-camox-focused] {
|
|
113
|
+
border-color: var(--camox-overlay-layout-color-selected);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* ---- Sheet overlay (dims non-selected blocks) ---- */
|
|
117
|
+
|
|
118
|
+
.camox-sheet-overlay {
|
|
119
|
+
position: absolute;
|
|
120
|
+
inset: 0;
|
|
121
|
+
background: rgba(0, 0, 0, 0.1);
|
|
122
|
+
backdrop-filter: blur(4px);
|
|
123
|
+
opacity: 0;
|
|
124
|
+
transition: opacity 0.3s ease-in-out;
|
|
125
|
+
pointer-events: none;
|
|
126
|
+
z-index: 20;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.camox-sheet-overlay[data-camox-visible] {
|
|
130
|
+
opacity: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ---- Add block control bar ---- */
|
|
134
|
+
|
|
135
|
+
.camox-add-block {
|
|
136
|
+
position: absolute;
|
|
137
|
+
left: 50%;
|
|
138
|
+
right: 0;
|
|
139
|
+
height: 36px;
|
|
140
|
+
width: fit-content;
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
justify-content: center;
|
|
144
|
+
z-index: 11;
|
|
145
|
+
transition: opacity 150ms ease;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.camox-add-block[data-camox-position="top"] {
|
|
149
|
+
top: 0;
|
|
150
|
+
transform: translateX(-50%) translateY(-50%);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.camox-add-block[data-camox-position="bottom"] {
|
|
154
|
+
bottom: 0;
|
|
155
|
+
transform: translateX(-50%) translateY(50%);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.camox-add-block[data-camox-hidden] {
|
|
159
|
+
opacity: 0;
|
|
160
|
+
pointer-events: none;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.camox-add-block-hitarea {
|
|
164
|
+
width: 120px;
|
|
165
|
+
height: 36px;
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
justify-content: center;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.camox-add-block-button {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: 0px;
|
|
175
|
+
padding: 0px;
|
|
176
|
+
width: 20px;
|
|
177
|
+
height: 20px;
|
|
178
|
+
justify-content: center;
|
|
179
|
+
background-color: var(--camox-overlay-color-selected);
|
|
180
|
+
color: white;
|
|
181
|
+
border: none;
|
|
182
|
+
border-radius: 9999px;
|
|
183
|
+
font-size: 12px;
|
|
184
|
+
font-weight: 500;
|
|
185
|
+
cursor: pointer;
|
|
186
|
+
white-space: nowrap;
|
|
187
|
+
transition: all 150ms ease;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.camox-add-block-button[data-camox-expanded] {
|
|
191
|
+
gap: 4px;
|
|
192
|
+
padding: 4px 8px;
|
|
193
|
+
width: auto;
|
|
194
|
+
height: auto;
|
|
195
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "camox",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"bin": {
|
|
5
5
|
"camox": "./bin/camox.mjs"
|
|
6
6
|
},
|
|
@@ -97,9 +97,9 @@
|
|
|
97
97
|
"react-dom": "^19.2.5",
|
|
98
98
|
"react-og-preview": "^0.2.0",
|
|
99
99
|
"shiki": "^4.0.2",
|
|
100
|
-
"@camox/
|
|
101
|
-
"@camox/
|
|
102
|
-
"@camox/ui": "0.7.
|
|
100
|
+
"@camox/cli": "0.7.3",
|
|
101
|
+
"@camox/api-contract": "0.7.3",
|
|
102
|
+
"@camox/ui": "0.7.3"
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
105
|
"@babel/core": "^7.29.0",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
},
|
|
127
127
|
"scripts": {
|
|
128
128
|
"dev": "tailwindcss -i ./src/studio.css -o ./dist/studio.css --watch",
|
|
129
|
-
"build": "tsdown && tailwindcss -i ./src/studio.css -o ./dist/studio.css --minify",
|
|
129
|
+
"build": "tsdown && tailwindcss -i ./src/studio.css -o ./dist/studio.css --minify && cp ./src/features/preview/studio-overlays.css ./dist/studio-overlays.css",
|
|
130
130
|
"build:watch": "tsdown --watch",
|
|
131
131
|
"lint": "oxlint",
|
|
132
132
|
"check": "tsgo --noEmit && oxlint --fix"
|