@ohhwells/bridge 0.1.2 → 0.1.5

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/index.js CHANGED
@@ -1,19 +1,4728 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
-
16
- // src/index.ts
17
- var index_exports = {};
18
- module.exports = __toCommonJS(index_exports);
1
+ // src/OhhwellsBridge.tsx
2
+ import React2, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+
4
+ // src/ui/toggle-group.tsx
5
+ import * as React from "react";
6
+
7
+ // node_modules/clsx/dist/clsx.mjs
8
+ function r(e) {
9
+ var t, f, n = "";
10
+ if ("string" == typeof e || "number" == typeof e) n += e;
11
+ else if ("object" == typeof e) if (Array.isArray(e)) {
12
+ var o = e.length;
13
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
14
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
15
+ return n;
16
+ }
17
+ function clsx() {
18
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
19
+ return n;
20
+ }
21
+
22
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
23
+ var concatArrays = (array1, array2) => {
24
+ const combinedArray = new Array(array1.length + array2.length);
25
+ for (let i = 0; i < array1.length; i++) {
26
+ combinedArray[i] = array1[i];
27
+ }
28
+ for (let i = 0; i < array2.length; i++) {
29
+ combinedArray[array1.length + i] = array2[i];
30
+ }
31
+ return combinedArray;
32
+ };
33
+ var createClassValidatorObject = (classGroupId, validator) => ({
34
+ classGroupId,
35
+ validator
36
+ });
37
+ var createClassPartObject = (nextPart = /* @__PURE__ */ new Map(), validators = null, classGroupId) => ({
38
+ nextPart,
39
+ validators,
40
+ classGroupId
41
+ });
42
+ var CLASS_PART_SEPARATOR = "-";
43
+ var EMPTY_CONFLICTS = [];
44
+ var ARBITRARY_PROPERTY_PREFIX = "arbitrary..";
45
+ var createClassGroupUtils = (config) => {
46
+ const classMap = createClassMap(config);
47
+ const {
48
+ conflictingClassGroups,
49
+ conflictingClassGroupModifiers
50
+ } = config;
51
+ const getClassGroupId = (className) => {
52
+ if (className.startsWith("[") && className.endsWith("]")) {
53
+ return getGroupIdForArbitraryProperty(className);
54
+ }
55
+ const classParts = className.split(CLASS_PART_SEPARATOR);
56
+ const startIndex = classParts[0] === "" && classParts.length > 1 ? 1 : 0;
57
+ return getGroupRecursive(classParts, startIndex, classMap);
58
+ };
59
+ const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {
60
+ if (hasPostfixModifier) {
61
+ const modifierConflicts = conflictingClassGroupModifiers[classGroupId];
62
+ const baseConflicts = conflictingClassGroups[classGroupId];
63
+ if (modifierConflicts) {
64
+ if (baseConflicts) {
65
+ return concatArrays(baseConflicts, modifierConflicts);
66
+ }
67
+ return modifierConflicts;
68
+ }
69
+ return baseConflicts || EMPTY_CONFLICTS;
70
+ }
71
+ return conflictingClassGroups[classGroupId] || EMPTY_CONFLICTS;
72
+ };
73
+ return {
74
+ getClassGroupId,
75
+ getConflictingClassGroupIds
76
+ };
77
+ };
78
+ var getGroupRecursive = (classParts, startIndex, classPartObject) => {
79
+ const classPathsLength = classParts.length - startIndex;
80
+ if (classPathsLength === 0) {
81
+ return classPartObject.classGroupId;
82
+ }
83
+ const currentClassPart = classParts[startIndex];
84
+ const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);
85
+ if (nextClassPartObject) {
86
+ const result = getGroupRecursive(classParts, startIndex + 1, nextClassPartObject);
87
+ if (result) return result;
88
+ }
89
+ const validators = classPartObject.validators;
90
+ if (validators === null) {
91
+ return void 0;
92
+ }
93
+ const classRest = startIndex === 0 ? classParts.join(CLASS_PART_SEPARATOR) : classParts.slice(startIndex).join(CLASS_PART_SEPARATOR);
94
+ const validatorsLength = validators.length;
95
+ for (let i = 0; i < validatorsLength; i++) {
96
+ const validatorObj = validators[i];
97
+ if (validatorObj.validator(classRest)) {
98
+ return validatorObj.classGroupId;
99
+ }
100
+ }
101
+ return void 0;
102
+ };
103
+ var getGroupIdForArbitraryProperty = (className) => className.slice(1, -1).indexOf(":") === -1 ? void 0 : (() => {
104
+ const content = className.slice(1, -1);
105
+ const colonIndex = content.indexOf(":");
106
+ const property = content.slice(0, colonIndex);
107
+ return property ? ARBITRARY_PROPERTY_PREFIX + property : void 0;
108
+ })();
109
+ var createClassMap = (config) => {
110
+ const {
111
+ theme,
112
+ classGroups
113
+ } = config;
114
+ return processClassGroups(classGroups, theme);
115
+ };
116
+ var processClassGroups = (classGroups, theme) => {
117
+ const classMap = createClassPartObject();
118
+ for (const classGroupId in classGroups) {
119
+ const group = classGroups[classGroupId];
120
+ processClassesRecursively(group, classMap, classGroupId, theme);
121
+ }
122
+ return classMap;
123
+ };
124
+ var processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {
125
+ const len = classGroup.length;
126
+ for (let i = 0; i < len; i++) {
127
+ const classDefinition = classGroup[i];
128
+ processClassDefinition(classDefinition, classPartObject, classGroupId, theme);
129
+ }
130
+ };
131
+ var processClassDefinition = (classDefinition, classPartObject, classGroupId, theme) => {
132
+ if (typeof classDefinition === "string") {
133
+ processStringDefinition(classDefinition, classPartObject, classGroupId);
134
+ return;
135
+ }
136
+ if (typeof classDefinition === "function") {
137
+ processFunctionDefinition(classDefinition, classPartObject, classGroupId, theme);
138
+ return;
139
+ }
140
+ processObjectDefinition(classDefinition, classPartObject, classGroupId, theme);
141
+ };
142
+ var processStringDefinition = (classDefinition, classPartObject, classGroupId) => {
143
+ const classPartObjectToEdit = classDefinition === "" ? classPartObject : getPart(classPartObject, classDefinition);
144
+ classPartObjectToEdit.classGroupId = classGroupId;
145
+ };
146
+ var processFunctionDefinition = (classDefinition, classPartObject, classGroupId, theme) => {
147
+ if (isThemeGetter(classDefinition)) {
148
+ processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);
149
+ return;
150
+ }
151
+ if (classPartObject.validators === null) {
152
+ classPartObject.validators = [];
153
+ }
154
+ classPartObject.validators.push(createClassValidatorObject(classGroupId, classDefinition));
155
+ };
156
+ var processObjectDefinition = (classDefinition, classPartObject, classGroupId, theme) => {
157
+ const entries = Object.entries(classDefinition);
158
+ const len = entries.length;
159
+ for (let i = 0; i < len; i++) {
160
+ const [key, value] = entries[i];
161
+ processClassesRecursively(value, getPart(classPartObject, key), classGroupId, theme);
162
+ }
163
+ };
164
+ var getPart = (classPartObject, path) => {
165
+ let current = classPartObject;
166
+ const parts = path.split(CLASS_PART_SEPARATOR);
167
+ const len = parts.length;
168
+ for (let i = 0; i < len; i++) {
169
+ const part = parts[i];
170
+ let next = current.nextPart.get(part);
171
+ if (!next) {
172
+ next = createClassPartObject();
173
+ current.nextPart.set(part, next);
174
+ }
175
+ current = next;
176
+ }
177
+ return current;
178
+ };
179
+ var isThemeGetter = (func) => "isThemeGetter" in func && func.isThemeGetter === true;
180
+ var createLruCache = (maxCacheSize) => {
181
+ if (maxCacheSize < 1) {
182
+ return {
183
+ get: () => void 0,
184
+ set: () => {
185
+ }
186
+ };
187
+ }
188
+ let cacheSize = 0;
189
+ let cache = /* @__PURE__ */ Object.create(null);
190
+ let previousCache = /* @__PURE__ */ Object.create(null);
191
+ const update = (key, value) => {
192
+ cache[key] = value;
193
+ cacheSize++;
194
+ if (cacheSize > maxCacheSize) {
195
+ cacheSize = 0;
196
+ previousCache = cache;
197
+ cache = /* @__PURE__ */ Object.create(null);
198
+ }
199
+ };
200
+ return {
201
+ get(key) {
202
+ let value = cache[key];
203
+ if (value !== void 0) {
204
+ return value;
205
+ }
206
+ if ((value = previousCache[key]) !== void 0) {
207
+ update(key, value);
208
+ return value;
209
+ }
210
+ },
211
+ set(key, value) {
212
+ if (key in cache) {
213
+ cache[key] = value;
214
+ } else {
215
+ update(key, value);
216
+ }
217
+ }
218
+ };
219
+ };
220
+ var IMPORTANT_MODIFIER = "!";
221
+ var MODIFIER_SEPARATOR = ":";
222
+ var EMPTY_MODIFIERS = [];
223
+ var createResultObject = (modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition, isExternal) => ({
224
+ modifiers,
225
+ hasImportantModifier,
226
+ baseClassName,
227
+ maybePostfixModifierPosition,
228
+ isExternal
229
+ });
230
+ var createParseClassName = (config) => {
231
+ const {
232
+ prefix,
233
+ experimentalParseClassName
234
+ } = config;
235
+ let parseClassName = (className) => {
236
+ const modifiers = [];
237
+ let bracketDepth = 0;
238
+ let parenDepth = 0;
239
+ let modifierStart = 0;
240
+ let postfixModifierPosition;
241
+ const len = className.length;
242
+ for (let index = 0; index < len; index++) {
243
+ const currentCharacter = className[index];
244
+ if (bracketDepth === 0 && parenDepth === 0) {
245
+ if (currentCharacter === MODIFIER_SEPARATOR) {
246
+ modifiers.push(className.slice(modifierStart, index));
247
+ modifierStart = index + 1;
248
+ continue;
249
+ }
250
+ if (currentCharacter === "/") {
251
+ postfixModifierPosition = index;
252
+ continue;
253
+ }
254
+ }
255
+ if (currentCharacter === "[") bracketDepth++;
256
+ else if (currentCharacter === "]") bracketDepth--;
257
+ else if (currentCharacter === "(") parenDepth++;
258
+ else if (currentCharacter === ")") parenDepth--;
259
+ }
260
+ const baseClassNameWithImportantModifier = modifiers.length === 0 ? className : className.slice(modifierStart);
261
+ let baseClassName = baseClassNameWithImportantModifier;
262
+ let hasImportantModifier = false;
263
+ if (baseClassNameWithImportantModifier.endsWith(IMPORTANT_MODIFIER)) {
264
+ baseClassName = baseClassNameWithImportantModifier.slice(0, -1);
265
+ hasImportantModifier = true;
266
+ } else if (
267
+ /**
268
+ * In Tailwind CSS v3 the important modifier was at the start of the base class name. This is still supported for legacy reasons.
269
+ * @see https://github.com/dcastil/tailwind-merge/issues/513#issuecomment-2614029864
270
+ */
271
+ baseClassNameWithImportantModifier.startsWith(IMPORTANT_MODIFIER)
272
+ ) {
273
+ baseClassName = baseClassNameWithImportantModifier.slice(1);
274
+ hasImportantModifier = true;
275
+ }
276
+ const maybePostfixModifierPosition = postfixModifierPosition && postfixModifierPosition > modifierStart ? postfixModifierPosition - modifierStart : void 0;
277
+ return createResultObject(modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition);
278
+ };
279
+ if (prefix) {
280
+ const fullPrefix = prefix + MODIFIER_SEPARATOR;
281
+ const parseClassNameOriginal = parseClassName;
282
+ parseClassName = (className) => className.startsWith(fullPrefix) ? parseClassNameOriginal(className.slice(fullPrefix.length)) : createResultObject(EMPTY_MODIFIERS, false, className, void 0, true);
283
+ }
284
+ if (experimentalParseClassName) {
285
+ const parseClassNameOriginal = parseClassName;
286
+ parseClassName = (className) => experimentalParseClassName({
287
+ className,
288
+ parseClassName: parseClassNameOriginal
289
+ });
290
+ }
291
+ return parseClassName;
292
+ };
293
+ var createSortModifiers = (config) => {
294
+ const modifierWeights = /* @__PURE__ */ new Map();
295
+ config.orderSensitiveModifiers.forEach((mod, index) => {
296
+ modifierWeights.set(mod, 1e6 + index);
297
+ });
298
+ return (modifiers) => {
299
+ const result = [];
300
+ let currentSegment = [];
301
+ for (let i = 0; i < modifiers.length; i++) {
302
+ const modifier = modifiers[i];
303
+ const isArbitrary = modifier[0] === "[";
304
+ const isOrderSensitive = modifierWeights.has(modifier);
305
+ if (isArbitrary || isOrderSensitive) {
306
+ if (currentSegment.length > 0) {
307
+ currentSegment.sort();
308
+ result.push(...currentSegment);
309
+ currentSegment = [];
310
+ }
311
+ result.push(modifier);
312
+ } else {
313
+ currentSegment.push(modifier);
314
+ }
315
+ }
316
+ if (currentSegment.length > 0) {
317
+ currentSegment.sort();
318
+ result.push(...currentSegment);
319
+ }
320
+ return result;
321
+ };
322
+ };
323
+ var createConfigUtils = (config) => ({
324
+ cache: createLruCache(config.cacheSize),
325
+ parseClassName: createParseClassName(config),
326
+ sortModifiers: createSortModifiers(config),
327
+ postfixLookupClassGroupIds: createPostfixLookupClassGroupIds(config),
328
+ ...createClassGroupUtils(config)
329
+ });
330
+ var createPostfixLookupClassGroupIds = (config) => {
331
+ const lookup = /* @__PURE__ */ Object.create(null);
332
+ const classGroupIds = config.postfixLookupClassGroups;
333
+ if (classGroupIds) {
334
+ for (let i = 0; i < classGroupIds.length; i++) {
335
+ lookup[classGroupIds[i]] = true;
336
+ }
337
+ }
338
+ return lookup;
339
+ };
340
+ var SPLIT_CLASSES_REGEX = /\s+/;
341
+ var mergeClassList = (classList, configUtils) => {
342
+ const {
343
+ parseClassName,
344
+ getClassGroupId,
345
+ getConflictingClassGroupIds,
346
+ sortModifiers,
347
+ postfixLookupClassGroupIds
348
+ } = configUtils;
349
+ const classGroupsInConflict = [];
350
+ const classNames = classList.trim().split(SPLIT_CLASSES_REGEX);
351
+ let result = "";
352
+ for (let index = classNames.length - 1; index >= 0; index -= 1) {
353
+ const originalClassName = classNames[index];
354
+ const {
355
+ isExternal,
356
+ modifiers,
357
+ hasImportantModifier,
358
+ baseClassName,
359
+ maybePostfixModifierPosition
360
+ } = parseClassName(originalClassName);
361
+ if (isExternal) {
362
+ result = originalClassName + (result.length > 0 ? " " + result : result);
363
+ continue;
364
+ }
365
+ let hasPostfixModifier = !!maybePostfixModifierPosition;
366
+ let classGroupId;
367
+ if (hasPostfixModifier) {
368
+ const baseClassNameWithoutPostfix = baseClassName.substring(0, maybePostfixModifierPosition);
369
+ classGroupId = getClassGroupId(baseClassNameWithoutPostfix);
370
+ const classGroupIdWithPostfix = classGroupId && postfixLookupClassGroupIds[classGroupId] ? getClassGroupId(baseClassName) : void 0;
371
+ if (classGroupIdWithPostfix && classGroupIdWithPostfix !== classGroupId) {
372
+ classGroupId = classGroupIdWithPostfix;
373
+ hasPostfixModifier = false;
374
+ }
375
+ } else {
376
+ classGroupId = getClassGroupId(baseClassName);
377
+ }
378
+ if (!classGroupId) {
379
+ if (!hasPostfixModifier) {
380
+ result = originalClassName + (result.length > 0 ? " " + result : result);
381
+ continue;
382
+ }
383
+ classGroupId = getClassGroupId(baseClassName);
384
+ if (!classGroupId) {
385
+ result = originalClassName + (result.length > 0 ? " " + result : result);
386
+ continue;
387
+ }
388
+ hasPostfixModifier = false;
389
+ }
390
+ const variantModifier = modifiers.length === 0 ? "" : modifiers.length === 1 ? modifiers[0] : sortModifiers(modifiers).join(":");
391
+ const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier;
392
+ const classId = modifierId + classGroupId;
393
+ if (classGroupsInConflict.indexOf(classId) > -1) {
394
+ continue;
395
+ }
396
+ classGroupsInConflict.push(classId);
397
+ const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier);
398
+ for (let i = 0; i < conflictGroups.length; ++i) {
399
+ const group = conflictGroups[i];
400
+ classGroupsInConflict.push(modifierId + group);
401
+ }
402
+ result = originalClassName + (result.length > 0 ? " " + result : result);
403
+ }
404
+ return result;
405
+ };
406
+ var twJoin = (...classLists) => {
407
+ let index = 0;
408
+ let argument;
409
+ let resolvedValue;
410
+ let string = "";
411
+ while (index < classLists.length) {
412
+ if (argument = classLists[index++]) {
413
+ if (resolvedValue = toValue(argument)) {
414
+ string && (string += " ");
415
+ string += resolvedValue;
416
+ }
417
+ }
418
+ }
419
+ return string;
420
+ };
421
+ var toValue = (mix) => {
422
+ if (typeof mix === "string") {
423
+ return mix;
424
+ }
425
+ let resolvedValue;
426
+ let string = "";
427
+ for (let k = 0; k < mix.length; k++) {
428
+ if (mix[k]) {
429
+ if (resolvedValue = toValue(mix[k])) {
430
+ string && (string += " ");
431
+ string += resolvedValue;
432
+ }
433
+ }
434
+ }
435
+ return string;
436
+ };
437
+ var createTailwindMerge = (createConfigFirst, ...createConfigRest) => {
438
+ let configUtils;
439
+ let cacheGet;
440
+ let cacheSet;
441
+ let functionToCall;
442
+ const initTailwindMerge = (classList) => {
443
+ const config = createConfigRest.reduce((previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), createConfigFirst());
444
+ configUtils = createConfigUtils(config);
445
+ cacheGet = configUtils.cache.get;
446
+ cacheSet = configUtils.cache.set;
447
+ functionToCall = tailwindMerge;
448
+ return tailwindMerge(classList);
449
+ };
450
+ const tailwindMerge = (classList) => {
451
+ const cachedResult = cacheGet(classList);
452
+ if (cachedResult) {
453
+ return cachedResult;
454
+ }
455
+ const result = mergeClassList(classList, configUtils);
456
+ cacheSet(classList, result);
457
+ return result;
458
+ };
459
+ functionToCall = initTailwindMerge;
460
+ return (...args) => functionToCall(twJoin(...args));
461
+ };
462
+ var fallbackThemeArr = [];
463
+ var fromTheme = (key) => {
464
+ const themeGetter = (theme) => theme[key] || fallbackThemeArr;
465
+ themeGetter.isThemeGetter = true;
466
+ return themeGetter;
467
+ };
468
+ var arbitraryValueRegex = /^\[(?:(\w[\w-]*):)?(.+)\]$/i;
469
+ var arbitraryVariableRegex = /^\((?:(\w[\w-]*):)?(.+)\)$/i;
470
+ var fractionRegex = /^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/;
471
+ var tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/;
472
+ var lengthUnitRegex = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/;
473
+ var colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/;
474
+ var shadowRegex = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/;
475
+ var imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/;
476
+ var isFraction = (value) => fractionRegex.test(value);
477
+ var isNumber = (value) => !!value && !Number.isNaN(Number(value));
478
+ var isInteger = (value) => !!value && Number.isInteger(Number(value));
479
+ var isPercent = (value) => value.endsWith("%") && isNumber(value.slice(0, -1));
480
+ var isTshirtSize = (value) => tshirtUnitRegex.test(value);
481
+ var isAny = () => true;
482
+ var isLengthOnly = (value) => (
483
+ // `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths.
484
+ // For example, `hsl(0 0% 0%)` would be classified as a length without this check.
485
+ // I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough.
486
+ lengthUnitRegex.test(value) && !colorFunctionRegex.test(value)
487
+ );
488
+ var isNever = () => false;
489
+ var isShadow = (value) => shadowRegex.test(value);
490
+ var isImage = (value) => imageRegex.test(value);
491
+ var isAnyNonArbitrary = (value) => !isArbitraryValue(value) && !isArbitraryVariable(value);
492
+ var isNamedContainerQuery = (value) => value.startsWith("@container") && (value[10] === "/" && value[11] !== void 0 || value[11] === "s" && value[16] !== void 0 && value.startsWith("-size/", 10) || value[11] === "n" && value[18] !== void 0 && value.startsWith("-normal/", 10));
493
+ var isArbitrarySize = (value) => getIsArbitraryValue(value, isLabelSize, isNever);
494
+ var isArbitraryValue = (value) => arbitraryValueRegex.test(value);
495
+ var isArbitraryLength = (value) => getIsArbitraryValue(value, isLabelLength, isLengthOnly);
496
+ var isArbitraryNumber = (value) => getIsArbitraryValue(value, isLabelNumber, isNumber);
497
+ var isArbitraryWeight = (value) => getIsArbitraryValue(value, isLabelWeight, isAny);
498
+ var isArbitraryFamilyName = (value) => getIsArbitraryValue(value, isLabelFamilyName, isNever);
499
+ var isArbitraryPosition = (value) => getIsArbitraryValue(value, isLabelPosition, isNever);
500
+ var isArbitraryImage = (value) => getIsArbitraryValue(value, isLabelImage, isImage);
501
+ var isArbitraryShadow = (value) => getIsArbitraryValue(value, isLabelShadow, isShadow);
502
+ var isArbitraryVariable = (value) => arbitraryVariableRegex.test(value);
503
+ var isArbitraryVariableLength = (value) => getIsArbitraryVariable(value, isLabelLength);
504
+ var isArbitraryVariableFamilyName = (value) => getIsArbitraryVariable(value, isLabelFamilyName);
505
+ var isArbitraryVariablePosition = (value) => getIsArbitraryVariable(value, isLabelPosition);
506
+ var isArbitraryVariableSize = (value) => getIsArbitraryVariable(value, isLabelSize);
507
+ var isArbitraryVariableImage = (value) => getIsArbitraryVariable(value, isLabelImage);
508
+ var isArbitraryVariableShadow = (value) => getIsArbitraryVariable(value, isLabelShadow, true);
509
+ var isArbitraryVariableWeight = (value) => getIsArbitraryVariable(value, isLabelWeight, true);
510
+ var getIsArbitraryValue = (value, testLabel, testValue) => {
511
+ const result = arbitraryValueRegex.exec(value);
512
+ if (result) {
513
+ if (result[1]) {
514
+ return testLabel(result[1]);
515
+ }
516
+ return testValue(result[2]);
517
+ }
518
+ return false;
519
+ };
520
+ var getIsArbitraryVariable = (value, testLabel, shouldMatchNoLabel = false) => {
521
+ const result = arbitraryVariableRegex.exec(value);
522
+ if (result) {
523
+ if (result[1]) {
524
+ return testLabel(result[1]);
525
+ }
526
+ return shouldMatchNoLabel;
527
+ }
528
+ return false;
529
+ };
530
+ var isLabelPosition = (label) => label === "position" || label === "percentage";
531
+ var isLabelImage = (label) => label === "image" || label === "url";
532
+ var isLabelSize = (label) => label === "length" || label === "size" || label === "bg-size";
533
+ var isLabelLength = (label) => label === "length";
534
+ var isLabelNumber = (label) => label === "number";
535
+ var isLabelFamilyName = (label) => label === "family-name";
536
+ var isLabelWeight = (label) => label === "number" || label === "weight";
537
+ var isLabelShadow = (label) => label === "shadow";
538
+ var getDefaultConfig = () => {
539
+ const themeColor = fromTheme("color");
540
+ const themeFont = fromTheme("font");
541
+ const themeText = fromTheme("text");
542
+ const themeFontWeight = fromTheme("font-weight");
543
+ const themeTracking = fromTheme("tracking");
544
+ const themeLeading = fromTheme("leading");
545
+ const themeBreakpoint = fromTheme("breakpoint");
546
+ const themeContainer = fromTheme("container");
547
+ const themeSpacing = fromTheme("spacing");
548
+ const themeRadius = fromTheme("radius");
549
+ const themeShadow = fromTheme("shadow");
550
+ const themeInsetShadow = fromTheme("inset-shadow");
551
+ const themeTextShadow = fromTheme("text-shadow");
552
+ const themeDropShadow = fromTheme("drop-shadow");
553
+ const themeBlur = fromTheme("blur");
554
+ const themePerspective = fromTheme("perspective");
555
+ const themeAspect = fromTheme("aspect");
556
+ const themeEase = fromTheme("ease");
557
+ const themeAnimate = fromTheme("animate");
558
+ const scaleBreak = () => ["auto", "avoid", "all", "avoid-page", "page", "left", "right", "column"];
559
+ const scalePosition = () => [
560
+ "center",
561
+ "top",
562
+ "bottom",
563
+ "left",
564
+ "right",
565
+ "top-left",
566
+ // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
567
+ "left-top",
568
+ "top-right",
569
+ // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
570
+ "right-top",
571
+ "bottom-right",
572
+ // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
573
+ "right-bottom",
574
+ "bottom-left",
575
+ // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
576
+ "left-bottom"
577
+ ];
578
+ const scalePositionWithArbitrary = () => [...scalePosition(), isArbitraryVariable, isArbitraryValue];
579
+ const scaleOverflow = () => ["auto", "hidden", "clip", "visible", "scroll"];
580
+ const scaleOverscroll = () => ["auto", "contain", "none"];
581
+ const scaleUnambiguousSpacing = () => [isArbitraryVariable, isArbitraryValue, themeSpacing];
582
+ const scaleInset = () => [isFraction, "full", "auto", ...scaleUnambiguousSpacing()];
583
+ const scaleGridTemplateColsRows = () => [isInteger, "none", "subgrid", isArbitraryVariable, isArbitraryValue];
584
+ const scaleGridColRowStartAndEnd = () => ["auto", {
585
+ span: ["full", isInteger, isArbitraryVariable, isArbitraryValue]
586
+ }, isInteger, isArbitraryVariable, isArbitraryValue];
587
+ const scaleGridColRowStartOrEnd = () => [isInteger, "auto", isArbitraryVariable, isArbitraryValue];
588
+ const scaleGridAutoColsRows = () => ["auto", "min", "max", "fr", isArbitraryVariable, isArbitraryValue];
589
+ const scaleAlignPrimaryAxis = () => ["start", "end", "center", "between", "around", "evenly", "stretch", "baseline", "center-safe", "end-safe"];
590
+ const scaleAlignSecondaryAxis = () => ["start", "end", "center", "stretch", "center-safe", "end-safe"];
591
+ const scaleMargin = () => ["auto", ...scaleUnambiguousSpacing()];
592
+ const scaleSizing = () => [isFraction, "auto", "full", "dvw", "dvh", "lvw", "lvh", "svw", "svh", "min", "max", "fit", ...scaleUnambiguousSpacing()];
593
+ const scaleSizingInline = () => [isFraction, "screen", "full", "dvw", "lvw", "svw", "min", "max", "fit", ...scaleUnambiguousSpacing()];
594
+ const scaleSizingBlock = () => [isFraction, "screen", "full", "lh", "dvh", "lvh", "svh", "min", "max", "fit", ...scaleUnambiguousSpacing()];
595
+ const scaleColor = () => [themeColor, isArbitraryVariable, isArbitraryValue];
596
+ const scaleBgPosition = () => [...scalePosition(), isArbitraryVariablePosition, isArbitraryPosition, {
597
+ position: [isArbitraryVariable, isArbitraryValue]
598
+ }];
599
+ const scaleBgRepeat = () => ["no-repeat", {
600
+ repeat: ["", "x", "y", "space", "round"]
601
+ }];
602
+ const scaleBgSize = () => ["auto", "cover", "contain", isArbitraryVariableSize, isArbitrarySize, {
603
+ size: [isArbitraryVariable, isArbitraryValue]
604
+ }];
605
+ const scaleGradientStopPosition = () => [isPercent, isArbitraryVariableLength, isArbitraryLength];
606
+ const scaleRadius = () => [
607
+ // Deprecated since Tailwind CSS v4.0.0
608
+ "",
609
+ "none",
610
+ "full",
611
+ themeRadius,
612
+ isArbitraryVariable,
613
+ isArbitraryValue
614
+ ];
615
+ const scaleBorderWidth = () => ["", isNumber, isArbitraryVariableLength, isArbitraryLength];
616
+ const scaleLineStyle = () => ["solid", "dashed", "dotted", "double"];
617
+ const scaleBlendMode = () => ["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"];
618
+ const scaleMaskImagePosition = () => [isNumber, isPercent, isArbitraryVariablePosition, isArbitraryPosition];
619
+ const scaleBlur = () => [
620
+ // Deprecated since Tailwind CSS v4.0.0
621
+ "",
622
+ "none",
623
+ themeBlur,
624
+ isArbitraryVariable,
625
+ isArbitraryValue
626
+ ];
627
+ const scaleRotate = () => ["none", isNumber, isArbitraryVariable, isArbitraryValue];
628
+ const scaleScale = () => ["none", isNumber, isArbitraryVariable, isArbitraryValue];
629
+ const scaleSkew = () => [isNumber, isArbitraryVariable, isArbitraryValue];
630
+ const scaleTranslate = () => [isFraction, "full", ...scaleUnambiguousSpacing()];
631
+ return {
632
+ cacheSize: 500,
633
+ theme: {
634
+ animate: ["spin", "ping", "pulse", "bounce"],
635
+ aspect: ["video"],
636
+ blur: [isTshirtSize],
637
+ breakpoint: [isTshirtSize],
638
+ color: [isAny],
639
+ container: [isTshirtSize],
640
+ "drop-shadow": [isTshirtSize],
641
+ ease: ["in", "out", "in-out"],
642
+ font: [isAnyNonArbitrary],
643
+ "font-weight": ["thin", "extralight", "light", "normal", "medium", "semibold", "bold", "extrabold", "black"],
644
+ "inset-shadow": [isTshirtSize],
645
+ leading: ["none", "tight", "snug", "normal", "relaxed", "loose"],
646
+ perspective: ["dramatic", "near", "normal", "midrange", "distant", "none"],
647
+ radius: [isTshirtSize],
648
+ shadow: [isTshirtSize],
649
+ spacing: ["px", isNumber],
650
+ text: [isTshirtSize],
651
+ "text-shadow": [isTshirtSize],
652
+ tracking: ["tighter", "tight", "normal", "wide", "wider", "widest"]
653
+ },
654
+ classGroups: {
655
+ // --------------
656
+ // --- Layout ---
657
+ // --------------
658
+ /**
659
+ * Aspect Ratio
660
+ * @see https://tailwindcss.com/docs/aspect-ratio
661
+ */
662
+ aspect: [{
663
+ aspect: ["auto", "square", isFraction, isArbitraryValue, isArbitraryVariable, themeAspect]
664
+ }],
665
+ /**
666
+ * Container
667
+ * @see https://tailwindcss.com/docs/container
668
+ * @deprecated since Tailwind CSS v4.0.0
669
+ */
670
+ container: ["container"],
671
+ /**
672
+ * Container Type
673
+ * @see https://tailwindcss.com/docs/responsive-design#container-queries
674
+ */
675
+ "container-type": [{
676
+ "@container": ["", "normal", "size", isArbitraryVariable, isArbitraryValue]
677
+ }],
678
+ /**
679
+ * Container Name
680
+ * @see https://tailwindcss.com/docs/responsive-design#named-containers
681
+ */
682
+ "container-named": [isNamedContainerQuery],
683
+ /**
684
+ * Columns
685
+ * @see https://tailwindcss.com/docs/columns
686
+ */
687
+ columns: [{
688
+ columns: [isNumber, isArbitraryValue, isArbitraryVariable, themeContainer]
689
+ }],
690
+ /**
691
+ * Break After
692
+ * @see https://tailwindcss.com/docs/break-after
693
+ */
694
+ "break-after": [{
695
+ "break-after": scaleBreak()
696
+ }],
697
+ /**
698
+ * Break Before
699
+ * @see https://tailwindcss.com/docs/break-before
700
+ */
701
+ "break-before": [{
702
+ "break-before": scaleBreak()
703
+ }],
704
+ /**
705
+ * Break Inside
706
+ * @see https://tailwindcss.com/docs/break-inside
707
+ */
708
+ "break-inside": [{
709
+ "break-inside": ["auto", "avoid", "avoid-page", "avoid-column"]
710
+ }],
711
+ /**
712
+ * Box Decoration Break
713
+ * @see https://tailwindcss.com/docs/box-decoration-break
714
+ */
715
+ "box-decoration": [{
716
+ "box-decoration": ["slice", "clone"]
717
+ }],
718
+ /**
719
+ * Box Sizing
720
+ * @see https://tailwindcss.com/docs/box-sizing
721
+ */
722
+ box: [{
723
+ box: ["border", "content"]
724
+ }],
725
+ /**
726
+ * Display
727
+ * @see https://tailwindcss.com/docs/display
728
+ */
729
+ display: ["block", "inline-block", "inline", "flex", "inline-flex", "table", "inline-table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row-group", "table-row", "flow-root", "grid", "inline-grid", "contents", "list-item", "hidden"],
730
+ /**
731
+ * Screen Reader Only
732
+ * @see https://tailwindcss.com/docs/display#screen-reader-only
733
+ */
734
+ sr: ["sr-only", "not-sr-only"],
735
+ /**
736
+ * Floats
737
+ * @see https://tailwindcss.com/docs/float
738
+ */
739
+ float: [{
740
+ float: ["right", "left", "none", "start", "end"]
741
+ }],
742
+ /**
743
+ * Clear
744
+ * @see https://tailwindcss.com/docs/clear
745
+ */
746
+ clear: [{
747
+ clear: ["left", "right", "both", "none", "start", "end"]
748
+ }],
749
+ /**
750
+ * Isolation
751
+ * @see https://tailwindcss.com/docs/isolation
752
+ */
753
+ isolation: ["isolate", "isolation-auto"],
754
+ /**
755
+ * Object Fit
756
+ * @see https://tailwindcss.com/docs/object-fit
757
+ */
758
+ "object-fit": [{
759
+ object: ["contain", "cover", "fill", "none", "scale-down"]
760
+ }],
761
+ /**
762
+ * Object Position
763
+ * @see https://tailwindcss.com/docs/object-position
764
+ */
765
+ "object-position": [{
766
+ object: scalePositionWithArbitrary()
767
+ }],
768
+ /**
769
+ * Overflow
770
+ * @see https://tailwindcss.com/docs/overflow
771
+ */
772
+ overflow: [{
773
+ overflow: scaleOverflow()
774
+ }],
775
+ /**
776
+ * Overflow X
777
+ * @see https://tailwindcss.com/docs/overflow
778
+ */
779
+ "overflow-x": [{
780
+ "overflow-x": scaleOverflow()
781
+ }],
782
+ /**
783
+ * Overflow Y
784
+ * @see https://tailwindcss.com/docs/overflow
785
+ */
786
+ "overflow-y": [{
787
+ "overflow-y": scaleOverflow()
788
+ }],
789
+ /**
790
+ * Overscroll Behavior
791
+ * @see https://tailwindcss.com/docs/overscroll-behavior
792
+ */
793
+ overscroll: [{
794
+ overscroll: scaleOverscroll()
795
+ }],
796
+ /**
797
+ * Overscroll Behavior X
798
+ * @see https://tailwindcss.com/docs/overscroll-behavior
799
+ */
800
+ "overscroll-x": [{
801
+ "overscroll-x": scaleOverscroll()
802
+ }],
803
+ /**
804
+ * Overscroll Behavior Y
805
+ * @see https://tailwindcss.com/docs/overscroll-behavior
806
+ */
807
+ "overscroll-y": [{
808
+ "overscroll-y": scaleOverscroll()
809
+ }],
810
+ /**
811
+ * Position
812
+ * @see https://tailwindcss.com/docs/position
813
+ */
814
+ position: ["static", "fixed", "absolute", "relative", "sticky"],
815
+ /**
816
+ * Inset
817
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
818
+ */
819
+ inset: [{
820
+ inset: scaleInset()
821
+ }],
822
+ /**
823
+ * Inset Inline
824
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
825
+ */
826
+ "inset-x": [{
827
+ "inset-x": scaleInset()
828
+ }],
829
+ /**
830
+ * Inset Block
831
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
832
+ */
833
+ "inset-y": [{
834
+ "inset-y": scaleInset()
835
+ }],
836
+ /**
837
+ * Inset Inline Start
838
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
839
+ * @todo class group will be renamed to `inset-s` in next major release
840
+ */
841
+ start: [{
842
+ "inset-s": scaleInset(),
843
+ /**
844
+ * @deprecated since Tailwind CSS v4.2.0 in favor of `inset-s-*` utilities.
845
+ * @see https://github.com/tailwindlabs/tailwindcss/pull/19613
846
+ */
847
+ start: scaleInset()
848
+ }],
849
+ /**
850
+ * Inset Inline End
851
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
852
+ * @todo class group will be renamed to `inset-e` in next major release
853
+ */
854
+ end: [{
855
+ "inset-e": scaleInset(),
856
+ /**
857
+ * @deprecated since Tailwind CSS v4.2.0 in favor of `inset-e-*` utilities.
858
+ * @see https://github.com/tailwindlabs/tailwindcss/pull/19613
859
+ */
860
+ end: scaleInset()
861
+ }],
862
+ /**
863
+ * Inset Block Start
864
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
865
+ */
866
+ "inset-bs": [{
867
+ "inset-bs": scaleInset()
868
+ }],
869
+ /**
870
+ * Inset Block End
871
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
872
+ */
873
+ "inset-be": [{
874
+ "inset-be": scaleInset()
875
+ }],
876
+ /**
877
+ * Top
878
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
879
+ */
880
+ top: [{
881
+ top: scaleInset()
882
+ }],
883
+ /**
884
+ * Right
885
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
886
+ */
887
+ right: [{
888
+ right: scaleInset()
889
+ }],
890
+ /**
891
+ * Bottom
892
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
893
+ */
894
+ bottom: [{
895
+ bottom: scaleInset()
896
+ }],
897
+ /**
898
+ * Left
899
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
900
+ */
901
+ left: [{
902
+ left: scaleInset()
903
+ }],
904
+ /**
905
+ * Visibility
906
+ * @see https://tailwindcss.com/docs/visibility
907
+ */
908
+ visibility: ["visible", "invisible", "collapse"],
909
+ /**
910
+ * Z-Index
911
+ * @see https://tailwindcss.com/docs/z-index
912
+ */
913
+ z: [{
914
+ z: [isInteger, "auto", isArbitraryVariable, isArbitraryValue]
915
+ }],
916
+ // ------------------------
917
+ // --- Flexbox and Grid ---
918
+ // ------------------------
919
+ /**
920
+ * Flex Basis
921
+ * @see https://tailwindcss.com/docs/flex-basis
922
+ */
923
+ basis: [{
924
+ basis: [isFraction, "full", "auto", themeContainer, ...scaleUnambiguousSpacing()]
925
+ }],
926
+ /**
927
+ * Flex Direction
928
+ * @see https://tailwindcss.com/docs/flex-direction
929
+ */
930
+ "flex-direction": [{
931
+ flex: ["row", "row-reverse", "col", "col-reverse"]
932
+ }],
933
+ /**
934
+ * Flex Wrap
935
+ * @see https://tailwindcss.com/docs/flex-wrap
936
+ */
937
+ "flex-wrap": [{
938
+ flex: ["nowrap", "wrap", "wrap-reverse"]
939
+ }],
940
+ /**
941
+ * Flex
942
+ * @see https://tailwindcss.com/docs/flex
943
+ */
944
+ flex: [{
945
+ flex: [isNumber, isFraction, "auto", "initial", "none", isArbitraryValue]
946
+ }],
947
+ /**
948
+ * Flex Grow
949
+ * @see https://tailwindcss.com/docs/flex-grow
950
+ */
951
+ grow: [{
952
+ grow: ["", isNumber, isArbitraryVariable, isArbitraryValue]
953
+ }],
954
+ /**
955
+ * Flex Shrink
956
+ * @see https://tailwindcss.com/docs/flex-shrink
957
+ */
958
+ shrink: [{
959
+ shrink: ["", isNumber, isArbitraryVariable, isArbitraryValue]
960
+ }],
961
+ /**
962
+ * Order
963
+ * @see https://tailwindcss.com/docs/order
964
+ */
965
+ order: [{
966
+ order: [isInteger, "first", "last", "none", isArbitraryVariable, isArbitraryValue]
967
+ }],
968
+ /**
969
+ * Grid Template Columns
970
+ * @see https://tailwindcss.com/docs/grid-template-columns
971
+ */
972
+ "grid-cols": [{
973
+ "grid-cols": scaleGridTemplateColsRows()
974
+ }],
975
+ /**
976
+ * Grid Column Start / End
977
+ * @see https://tailwindcss.com/docs/grid-column
978
+ */
979
+ "col-start-end": [{
980
+ col: scaleGridColRowStartAndEnd()
981
+ }],
982
+ /**
983
+ * Grid Column Start
984
+ * @see https://tailwindcss.com/docs/grid-column
985
+ */
986
+ "col-start": [{
987
+ "col-start": scaleGridColRowStartOrEnd()
988
+ }],
989
+ /**
990
+ * Grid Column End
991
+ * @see https://tailwindcss.com/docs/grid-column
992
+ */
993
+ "col-end": [{
994
+ "col-end": scaleGridColRowStartOrEnd()
995
+ }],
996
+ /**
997
+ * Grid Template Rows
998
+ * @see https://tailwindcss.com/docs/grid-template-rows
999
+ */
1000
+ "grid-rows": [{
1001
+ "grid-rows": scaleGridTemplateColsRows()
1002
+ }],
1003
+ /**
1004
+ * Grid Row Start / End
1005
+ * @see https://tailwindcss.com/docs/grid-row
1006
+ */
1007
+ "row-start-end": [{
1008
+ row: scaleGridColRowStartAndEnd()
1009
+ }],
1010
+ /**
1011
+ * Grid Row Start
1012
+ * @see https://tailwindcss.com/docs/grid-row
1013
+ */
1014
+ "row-start": [{
1015
+ "row-start": scaleGridColRowStartOrEnd()
1016
+ }],
1017
+ /**
1018
+ * Grid Row End
1019
+ * @see https://tailwindcss.com/docs/grid-row
1020
+ */
1021
+ "row-end": [{
1022
+ "row-end": scaleGridColRowStartOrEnd()
1023
+ }],
1024
+ /**
1025
+ * Grid Auto Flow
1026
+ * @see https://tailwindcss.com/docs/grid-auto-flow
1027
+ */
1028
+ "grid-flow": [{
1029
+ "grid-flow": ["row", "col", "dense", "row-dense", "col-dense"]
1030
+ }],
1031
+ /**
1032
+ * Grid Auto Columns
1033
+ * @see https://tailwindcss.com/docs/grid-auto-columns
1034
+ */
1035
+ "auto-cols": [{
1036
+ "auto-cols": scaleGridAutoColsRows()
1037
+ }],
1038
+ /**
1039
+ * Grid Auto Rows
1040
+ * @see https://tailwindcss.com/docs/grid-auto-rows
1041
+ */
1042
+ "auto-rows": [{
1043
+ "auto-rows": scaleGridAutoColsRows()
1044
+ }],
1045
+ /**
1046
+ * Gap
1047
+ * @see https://tailwindcss.com/docs/gap
1048
+ */
1049
+ gap: [{
1050
+ gap: scaleUnambiguousSpacing()
1051
+ }],
1052
+ /**
1053
+ * Gap X
1054
+ * @see https://tailwindcss.com/docs/gap
1055
+ */
1056
+ "gap-x": [{
1057
+ "gap-x": scaleUnambiguousSpacing()
1058
+ }],
1059
+ /**
1060
+ * Gap Y
1061
+ * @see https://tailwindcss.com/docs/gap
1062
+ */
1063
+ "gap-y": [{
1064
+ "gap-y": scaleUnambiguousSpacing()
1065
+ }],
1066
+ /**
1067
+ * Justify Content
1068
+ * @see https://tailwindcss.com/docs/justify-content
1069
+ */
1070
+ "justify-content": [{
1071
+ justify: [...scaleAlignPrimaryAxis(), "normal"]
1072
+ }],
1073
+ /**
1074
+ * Justify Items
1075
+ * @see https://tailwindcss.com/docs/justify-items
1076
+ */
1077
+ "justify-items": [{
1078
+ "justify-items": [...scaleAlignSecondaryAxis(), "normal"]
1079
+ }],
1080
+ /**
1081
+ * Justify Self
1082
+ * @see https://tailwindcss.com/docs/justify-self
1083
+ */
1084
+ "justify-self": [{
1085
+ "justify-self": ["auto", ...scaleAlignSecondaryAxis()]
1086
+ }],
1087
+ /**
1088
+ * Align Content
1089
+ * @see https://tailwindcss.com/docs/align-content
1090
+ */
1091
+ "align-content": [{
1092
+ content: ["normal", ...scaleAlignPrimaryAxis()]
1093
+ }],
1094
+ /**
1095
+ * Align Items
1096
+ * @see https://tailwindcss.com/docs/align-items
1097
+ */
1098
+ "align-items": [{
1099
+ items: [...scaleAlignSecondaryAxis(), {
1100
+ baseline: ["", "last"]
1101
+ }]
1102
+ }],
1103
+ /**
1104
+ * Align Self
1105
+ * @see https://tailwindcss.com/docs/align-self
1106
+ */
1107
+ "align-self": [{
1108
+ self: ["auto", ...scaleAlignSecondaryAxis(), {
1109
+ baseline: ["", "last"]
1110
+ }]
1111
+ }],
1112
+ /**
1113
+ * Place Content
1114
+ * @see https://tailwindcss.com/docs/place-content
1115
+ */
1116
+ "place-content": [{
1117
+ "place-content": scaleAlignPrimaryAxis()
1118
+ }],
1119
+ /**
1120
+ * Place Items
1121
+ * @see https://tailwindcss.com/docs/place-items
1122
+ */
1123
+ "place-items": [{
1124
+ "place-items": [...scaleAlignSecondaryAxis(), "baseline"]
1125
+ }],
1126
+ /**
1127
+ * Place Self
1128
+ * @see https://tailwindcss.com/docs/place-self
1129
+ */
1130
+ "place-self": [{
1131
+ "place-self": ["auto", ...scaleAlignSecondaryAxis()]
1132
+ }],
1133
+ // Spacing
1134
+ /**
1135
+ * Padding
1136
+ * @see https://tailwindcss.com/docs/padding
1137
+ */
1138
+ p: [{
1139
+ p: scaleUnambiguousSpacing()
1140
+ }],
1141
+ /**
1142
+ * Padding Inline
1143
+ * @see https://tailwindcss.com/docs/padding
1144
+ */
1145
+ px: [{
1146
+ px: scaleUnambiguousSpacing()
1147
+ }],
1148
+ /**
1149
+ * Padding Block
1150
+ * @see https://tailwindcss.com/docs/padding
1151
+ */
1152
+ py: [{
1153
+ py: scaleUnambiguousSpacing()
1154
+ }],
1155
+ /**
1156
+ * Padding Inline Start
1157
+ * @see https://tailwindcss.com/docs/padding
1158
+ */
1159
+ ps: [{
1160
+ ps: scaleUnambiguousSpacing()
1161
+ }],
1162
+ /**
1163
+ * Padding Inline End
1164
+ * @see https://tailwindcss.com/docs/padding
1165
+ */
1166
+ pe: [{
1167
+ pe: scaleUnambiguousSpacing()
1168
+ }],
1169
+ /**
1170
+ * Padding Block Start
1171
+ * @see https://tailwindcss.com/docs/padding
1172
+ */
1173
+ pbs: [{
1174
+ pbs: scaleUnambiguousSpacing()
1175
+ }],
1176
+ /**
1177
+ * Padding Block End
1178
+ * @see https://tailwindcss.com/docs/padding
1179
+ */
1180
+ pbe: [{
1181
+ pbe: scaleUnambiguousSpacing()
1182
+ }],
1183
+ /**
1184
+ * Padding Top
1185
+ * @see https://tailwindcss.com/docs/padding
1186
+ */
1187
+ pt: [{
1188
+ pt: scaleUnambiguousSpacing()
1189
+ }],
1190
+ /**
1191
+ * Padding Right
1192
+ * @see https://tailwindcss.com/docs/padding
1193
+ */
1194
+ pr: [{
1195
+ pr: scaleUnambiguousSpacing()
1196
+ }],
1197
+ /**
1198
+ * Padding Bottom
1199
+ * @see https://tailwindcss.com/docs/padding
1200
+ */
1201
+ pb: [{
1202
+ pb: scaleUnambiguousSpacing()
1203
+ }],
1204
+ /**
1205
+ * Padding Left
1206
+ * @see https://tailwindcss.com/docs/padding
1207
+ */
1208
+ pl: [{
1209
+ pl: scaleUnambiguousSpacing()
1210
+ }],
1211
+ /**
1212
+ * Margin
1213
+ * @see https://tailwindcss.com/docs/margin
1214
+ */
1215
+ m: [{
1216
+ m: scaleMargin()
1217
+ }],
1218
+ /**
1219
+ * Margin Inline
1220
+ * @see https://tailwindcss.com/docs/margin
1221
+ */
1222
+ mx: [{
1223
+ mx: scaleMargin()
1224
+ }],
1225
+ /**
1226
+ * Margin Block
1227
+ * @see https://tailwindcss.com/docs/margin
1228
+ */
1229
+ my: [{
1230
+ my: scaleMargin()
1231
+ }],
1232
+ /**
1233
+ * Margin Inline Start
1234
+ * @see https://tailwindcss.com/docs/margin
1235
+ */
1236
+ ms: [{
1237
+ ms: scaleMargin()
1238
+ }],
1239
+ /**
1240
+ * Margin Inline End
1241
+ * @see https://tailwindcss.com/docs/margin
1242
+ */
1243
+ me: [{
1244
+ me: scaleMargin()
1245
+ }],
1246
+ /**
1247
+ * Margin Block Start
1248
+ * @see https://tailwindcss.com/docs/margin
1249
+ */
1250
+ mbs: [{
1251
+ mbs: scaleMargin()
1252
+ }],
1253
+ /**
1254
+ * Margin Block End
1255
+ * @see https://tailwindcss.com/docs/margin
1256
+ */
1257
+ mbe: [{
1258
+ mbe: scaleMargin()
1259
+ }],
1260
+ /**
1261
+ * Margin Top
1262
+ * @see https://tailwindcss.com/docs/margin
1263
+ */
1264
+ mt: [{
1265
+ mt: scaleMargin()
1266
+ }],
1267
+ /**
1268
+ * Margin Right
1269
+ * @see https://tailwindcss.com/docs/margin
1270
+ */
1271
+ mr: [{
1272
+ mr: scaleMargin()
1273
+ }],
1274
+ /**
1275
+ * Margin Bottom
1276
+ * @see https://tailwindcss.com/docs/margin
1277
+ */
1278
+ mb: [{
1279
+ mb: scaleMargin()
1280
+ }],
1281
+ /**
1282
+ * Margin Left
1283
+ * @see https://tailwindcss.com/docs/margin
1284
+ */
1285
+ ml: [{
1286
+ ml: scaleMargin()
1287
+ }],
1288
+ /**
1289
+ * Space Between X
1290
+ * @see https://tailwindcss.com/docs/margin#adding-space-between-children
1291
+ */
1292
+ "space-x": [{
1293
+ "space-x": scaleUnambiguousSpacing()
1294
+ }],
1295
+ /**
1296
+ * Space Between X Reverse
1297
+ * @see https://tailwindcss.com/docs/margin#adding-space-between-children
1298
+ */
1299
+ "space-x-reverse": ["space-x-reverse"],
1300
+ /**
1301
+ * Space Between Y
1302
+ * @see https://tailwindcss.com/docs/margin#adding-space-between-children
1303
+ */
1304
+ "space-y": [{
1305
+ "space-y": scaleUnambiguousSpacing()
1306
+ }],
1307
+ /**
1308
+ * Space Between Y Reverse
1309
+ * @see https://tailwindcss.com/docs/margin#adding-space-between-children
1310
+ */
1311
+ "space-y-reverse": ["space-y-reverse"],
1312
+ // --------------
1313
+ // --- Sizing ---
1314
+ // --------------
1315
+ /**
1316
+ * Size
1317
+ * @see https://tailwindcss.com/docs/width#setting-both-width-and-height
1318
+ */
1319
+ size: [{
1320
+ size: scaleSizing()
1321
+ }],
1322
+ /**
1323
+ * Inline Size
1324
+ * @see https://tailwindcss.com/docs/width
1325
+ */
1326
+ "inline-size": [{
1327
+ inline: ["auto", ...scaleSizingInline()]
1328
+ }],
1329
+ /**
1330
+ * Min-Inline Size
1331
+ * @see https://tailwindcss.com/docs/min-width
1332
+ */
1333
+ "min-inline-size": [{
1334
+ "min-inline": ["auto", ...scaleSizingInline()]
1335
+ }],
1336
+ /**
1337
+ * Max-Inline Size
1338
+ * @see https://tailwindcss.com/docs/max-width
1339
+ */
1340
+ "max-inline-size": [{
1341
+ "max-inline": ["none", ...scaleSizingInline()]
1342
+ }],
1343
+ /**
1344
+ * Block Size
1345
+ * @see https://tailwindcss.com/docs/height
1346
+ */
1347
+ "block-size": [{
1348
+ block: ["auto", ...scaleSizingBlock()]
1349
+ }],
1350
+ /**
1351
+ * Min-Block Size
1352
+ * @see https://tailwindcss.com/docs/min-height
1353
+ */
1354
+ "min-block-size": [{
1355
+ "min-block": ["auto", ...scaleSizingBlock()]
1356
+ }],
1357
+ /**
1358
+ * Max-Block Size
1359
+ * @see https://tailwindcss.com/docs/max-height
1360
+ */
1361
+ "max-block-size": [{
1362
+ "max-block": ["none", ...scaleSizingBlock()]
1363
+ }],
1364
+ /**
1365
+ * Width
1366
+ * @see https://tailwindcss.com/docs/width
1367
+ */
1368
+ w: [{
1369
+ w: [themeContainer, "screen", ...scaleSizing()]
1370
+ }],
1371
+ /**
1372
+ * Min-Width
1373
+ * @see https://tailwindcss.com/docs/min-width
1374
+ */
1375
+ "min-w": [{
1376
+ "min-w": [
1377
+ themeContainer,
1378
+ "screen",
1379
+ /** Deprecated. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
1380
+ "none",
1381
+ ...scaleSizing()
1382
+ ]
1383
+ }],
1384
+ /**
1385
+ * Max-Width
1386
+ * @see https://tailwindcss.com/docs/max-width
1387
+ */
1388
+ "max-w": [{
1389
+ "max-w": [
1390
+ themeContainer,
1391
+ "screen",
1392
+ "none",
1393
+ /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
1394
+ "prose",
1395
+ /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
1396
+ {
1397
+ screen: [themeBreakpoint]
1398
+ },
1399
+ ...scaleSizing()
1400
+ ]
1401
+ }],
1402
+ /**
1403
+ * Height
1404
+ * @see https://tailwindcss.com/docs/height
1405
+ */
1406
+ h: [{
1407
+ h: ["screen", "lh", ...scaleSizing()]
1408
+ }],
1409
+ /**
1410
+ * Min-Height
1411
+ * @see https://tailwindcss.com/docs/min-height
1412
+ */
1413
+ "min-h": [{
1414
+ "min-h": ["screen", "lh", "none", ...scaleSizing()]
1415
+ }],
1416
+ /**
1417
+ * Max-Height
1418
+ * @see https://tailwindcss.com/docs/max-height
1419
+ */
1420
+ "max-h": [{
1421
+ "max-h": ["screen", "lh", ...scaleSizing()]
1422
+ }],
1423
+ // ------------------
1424
+ // --- Typography ---
1425
+ // ------------------
1426
+ /**
1427
+ * Font Size
1428
+ * @see https://tailwindcss.com/docs/font-size
1429
+ */
1430
+ "font-size": [{
1431
+ text: ["base", themeText, isArbitraryVariableLength, isArbitraryLength]
1432
+ }],
1433
+ /**
1434
+ * Font Smoothing
1435
+ * @see https://tailwindcss.com/docs/font-smoothing
1436
+ */
1437
+ "font-smoothing": ["antialiased", "subpixel-antialiased"],
1438
+ /**
1439
+ * Font Style
1440
+ * @see https://tailwindcss.com/docs/font-style
1441
+ */
1442
+ "font-style": ["italic", "not-italic"],
1443
+ /**
1444
+ * Font Weight
1445
+ * @see https://tailwindcss.com/docs/font-weight
1446
+ */
1447
+ "font-weight": [{
1448
+ font: [themeFontWeight, isArbitraryVariableWeight, isArbitraryWeight]
1449
+ }],
1450
+ /**
1451
+ * Font Stretch
1452
+ * @see https://tailwindcss.com/docs/font-stretch
1453
+ */
1454
+ "font-stretch": [{
1455
+ "font-stretch": ["ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "normal", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded", isPercent, isArbitraryValue]
1456
+ }],
1457
+ /**
1458
+ * Font Family
1459
+ * @see https://tailwindcss.com/docs/font-family
1460
+ */
1461
+ "font-family": [{
1462
+ font: [isArbitraryVariableFamilyName, isArbitraryFamilyName, themeFont]
1463
+ }],
1464
+ /**
1465
+ * Font Feature Settings
1466
+ * @see https://tailwindcss.com/docs/font-feature-settings
1467
+ */
1468
+ "font-features": [{
1469
+ "font-features": [isArbitraryValue]
1470
+ }],
1471
+ /**
1472
+ * Font Variant Numeric
1473
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1474
+ */
1475
+ "fvn-normal": ["normal-nums"],
1476
+ /**
1477
+ * Font Variant Numeric
1478
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1479
+ */
1480
+ "fvn-ordinal": ["ordinal"],
1481
+ /**
1482
+ * Font Variant Numeric
1483
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1484
+ */
1485
+ "fvn-slashed-zero": ["slashed-zero"],
1486
+ /**
1487
+ * Font Variant Numeric
1488
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1489
+ */
1490
+ "fvn-figure": ["lining-nums", "oldstyle-nums"],
1491
+ /**
1492
+ * Font Variant Numeric
1493
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1494
+ */
1495
+ "fvn-spacing": ["proportional-nums", "tabular-nums"],
1496
+ /**
1497
+ * Font Variant Numeric
1498
+ * @see https://tailwindcss.com/docs/font-variant-numeric
1499
+ */
1500
+ "fvn-fraction": ["diagonal-fractions", "stacked-fractions"],
1501
+ /**
1502
+ * Letter Spacing
1503
+ * @see https://tailwindcss.com/docs/letter-spacing
1504
+ */
1505
+ tracking: [{
1506
+ tracking: [themeTracking, isArbitraryVariable, isArbitraryValue]
1507
+ }],
1508
+ /**
1509
+ * Line Clamp
1510
+ * @see https://tailwindcss.com/docs/line-clamp
1511
+ */
1512
+ "line-clamp": [{
1513
+ "line-clamp": [isNumber, "none", isArbitraryVariable, isArbitraryNumber]
1514
+ }],
1515
+ /**
1516
+ * Line Height
1517
+ * @see https://tailwindcss.com/docs/line-height
1518
+ */
1519
+ leading: [{
1520
+ leading: [
1521
+ /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
1522
+ themeLeading,
1523
+ ...scaleUnambiguousSpacing()
1524
+ ]
1525
+ }],
1526
+ /**
1527
+ * List Style Image
1528
+ * @see https://tailwindcss.com/docs/list-style-image
1529
+ */
1530
+ "list-image": [{
1531
+ "list-image": ["none", isArbitraryVariable, isArbitraryValue]
1532
+ }],
1533
+ /**
1534
+ * List Style Position
1535
+ * @see https://tailwindcss.com/docs/list-style-position
1536
+ */
1537
+ "list-style-position": [{
1538
+ list: ["inside", "outside"]
1539
+ }],
1540
+ /**
1541
+ * List Style Type
1542
+ * @see https://tailwindcss.com/docs/list-style-type
1543
+ */
1544
+ "list-style-type": [{
1545
+ list: ["disc", "decimal", "none", isArbitraryVariable, isArbitraryValue]
1546
+ }],
1547
+ /**
1548
+ * Text Alignment
1549
+ * @see https://tailwindcss.com/docs/text-align
1550
+ */
1551
+ "text-alignment": [{
1552
+ text: ["left", "center", "right", "justify", "start", "end"]
1553
+ }],
1554
+ /**
1555
+ * Placeholder Color
1556
+ * @deprecated since Tailwind CSS v3.0.0
1557
+ * @see https://v3.tailwindcss.com/docs/placeholder-color
1558
+ */
1559
+ "placeholder-color": [{
1560
+ placeholder: scaleColor()
1561
+ }],
1562
+ /**
1563
+ * Text Color
1564
+ * @see https://tailwindcss.com/docs/text-color
1565
+ */
1566
+ "text-color": [{
1567
+ text: scaleColor()
1568
+ }],
1569
+ /**
1570
+ * Text Decoration
1571
+ * @see https://tailwindcss.com/docs/text-decoration
1572
+ */
1573
+ "text-decoration": ["underline", "overline", "line-through", "no-underline"],
1574
+ /**
1575
+ * Text Decoration Style
1576
+ * @see https://tailwindcss.com/docs/text-decoration-style
1577
+ */
1578
+ "text-decoration-style": [{
1579
+ decoration: [...scaleLineStyle(), "wavy"]
1580
+ }],
1581
+ /**
1582
+ * Text Decoration Thickness
1583
+ * @see https://tailwindcss.com/docs/text-decoration-thickness
1584
+ */
1585
+ "text-decoration-thickness": [{
1586
+ decoration: [isNumber, "from-font", "auto", isArbitraryVariable, isArbitraryLength]
1587
+ }],
1588
+ /**
1589
+ * Text Decoration Color
1590
+ * @see https://tailwindcss.com/docs/text-decoration-color
1591
+ */
1592
+ "text-decoration-color": [{
1593
+ decoration: scaleColor()
1594
+ }],
1595
+ /**
1596
+ * Text Underline Offset
1597
+ * @see https://tailwindcss.com/docs/text-underline-offset
1598
+ */
1599
+ "underline-offset": [{
1600
+ "underline-offset": [isNumber, "auto", isArbitraryVariable, isArbitraryValue]
1601
+ }],
1602
+ /**
1603
+ * Text Transform
1604
+ * @see https://tailwindcss.com/docs/text-transform
1605
+ */
1606
+ "text-transform": ["uppercase", "lowercase", "capitalize", "normal-case"],
1607
+ /**
1608
+ * Text Overflow
1609
+ * @see https://tailwindcss.com/docs/text-overflow
1610
+ */
1611
+ "text-overflow": ["truncate", "text-ellipsis", "text-clip"],
1612
+ /**
1613
+ * Text Wrap
1614
+ * @see https://tailwindcss.com/docs/text-wrap
1615
+ */
1616
+ "text-wrap": [{
1617
+ text: ["wrap", "nowrap", "balance", "pretty"]
1618
+ }],
1619
+ /**
1620
+ * Text Indent
1621
+ * @see https://tailwindcss.com/docs/text-indent
1622
+ */
1623
+ indent: [{
1624
+ indent: scaleUnambiguousSpacing()
1625
+ }],
1626
+ /**
1627
+ * Tab Size
1628
+ * @see https://tailwindcss.com/docs/tab-size
1629
+ */
1630
+ "tab-size": [{
1631
+ tab: [isInteger, isArbitraryVariable, isArbitraryValue]
1632
+ }],
1633
+ /**
1634
+ * Vertical Alignment
1635
+ * @see https://tailwindcss.com/docs/vertical-align
1636
+ */
1637
+ "vertical-align": [{
1638
+ align: ["baseline", "top", "middle", "bottom", "text-top", "text-bottom", "sub", "super", isArbitraryVariable, isArbitraryValue]
1639
+ }],
1640
+ /**
1641
+ * Whitespace
1642
+ * @see https://tailwindcss.com/docs/whitespace
1643
+ */
1644
+ whitespace: [{
1645
+ whitespace: ["normal", "nowrap", "pre", "pre-line", "pre-wrap", "break-spaces"]
1646
+ }],
1647
+ /**
1648
+ * Word Break
1649
+ * @see https://tailwindcss.com/docs/word-break
1650
+ */
1651
+ break: [{
1652
+ break: ["normal", "words", "all", "keep"]
1653
+ }],
1654
+ /**
1655
+ * Overflow Wrap
1656
+ * @see https://tailwindcss.com/docs/overflow-wrap
1657
+ */
1658
+ wrap: [{
1659
+ wrap: ["break-word", "anywhere", "normal"]
1660
+ }],
1661
+ /**
1662
+ * Hyphens
1663
+ * @see https://tailwindcss.com/docs/hyphens
1664
+ */
1665
+ hyphens: [{
1666
+ hyphens: ["none", "manual", "auto"]
1667
+ }],
1668
+ /**
1669
+ * Content
1670
+ * @see https://tailwindcss.com/docs/content
1671
+ */
1672
+ content: [{
1673
+ content: ["none", isArbitraryVariable, isArbitraryValue]
1674
+ }],
1675
+ // -------------------
1676
+ // --- Backgrounds ---
1677
+ // -------------------
1678
+ /**
1679
+ * Background Attachment
1680
+ * @see https://tailwindcss.com/docs/background-attachment
1681
+ */
1682
+ "bg-attachment": [{
1683
+ bg: ["fixed", "local", "scroll"]
1684
+ }],
1685
+ /**
1686
+ * Background Clip
1687
+ * @see https://tailwindcss.com/docs/background-clip
1688
+ */
1689
+ "bg-clip": [{
1690
+ "bg-clip": ["border", "padding", "content", "text"]
1691
+ }],
1692
+ /**
1693
+ * Background Origin
1694
+ * @see https://tailwindcss.com/docs/background-origin
1695
+ */
1696
+ "bg-origin": [{
1697
+ "bg-origin": ["border", "padding", "content"]
1698
+ }],
1699
+ /**
1700
+ * Background Position
1701
+ * @see https://tailwindcss.com/docs/background-position
1702
+ */
1703
+ "bg-position": [{
1704
+ bg: scaleBgPosition()
1705
+ }],
1706
+ /**
1707
+ * Background Repeat
1708
+ * @see https://tailwindcss.com/docs/background-repeat
1709
+ */
1710
+ "bg-repeat": [{
1711
+ bg: scaleBgRepeat()
1712
+ }],
1713
+ /**
1714
+ * Background Size
1715
+ * @see https://tailwindcss.com/docs/background-size
1716
+ */
1717
+ "bg-size": [{
1718
+ bg: scaleBgSize()
1719
+ }],
1720
+ /**
1721
+ * Background Image
1722
+ * @see https://tailwindcss.com/docs/background-image
1723
+ */
1724
+ "bg-image": [{
1725
+ bg: ["none", {
1726
+ linear: [{
1727
+ to: ["t", "tr", "r", "br", "b", "bl", "l", "tl"]
1728
+ }, isInteger, isArbitraryVariable, isArbitraryValue],
1729
+ radial: ["", isArbitraryVariable, isArbitraryValue],
1730
+ conic: [isInteger, isArbitraryVariable, isArbitraryValue]
1731
+ }, isArbitraryVariableImage, isArbitraryImage]
1732
+ }],
1733
+ /**
1734
+ * Background Color
1735
+ * @see https://tailwindcss.com/docs/background-color
1736
+ */
1737
+ "bg-color": [{
1738
+ bg: scaleColor()
1739
+ }],
1740
+ /**
1741
+ * Gradient Color Stops From Position
1742
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1743
+ */
1744
+ "gradient-from-pos": [{
1745
+ from: scaleGradientStopPosition()
1746
+ }],
1747
+ /**
1748
+ * Gradient Color Stops Via Position
1749
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1750
+ */
1751
+ "gradient-via-pos": [{
1752
+ via: scaleGradientStopPosition()
1753
+ }],
1754
+ /**
1755
+ * Gradient Color Stops To Position
1756
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1757
+ */
1758
+ "gradient-to-pos": [{
1759
+ to: scaleGradientStopPosition()
1760
+ }],
1761
+ /**
1762
+ * Gradient Color Stops From
1763
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1764
+ */
1765
+ "gradient-from": [{
1766
+ from: scaleColor()
1767
+ }],
1768
+ /**
1769
+ * Gradient Color Stops Via
1770
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1771
+ */
1772
+ "gradient-via": [{
1773
+ via: scaleColor()
1774
+ }],
1775
+ /**
1776
+ * Gradient Color Stops To
1777
+ * @see https://tailwindcss.com/docs/gradient-color-stops
1778
+ */
1779
+ "gradient-to": [{
1780
+ to: scaleColor()
1781
+ }],
1782
+ // ---------------
1783
+ // --- Borders ---
1784
+ // ---------------
1785
+ /**
1786
+ * Border Radius
1787
+ * @see https://tailwindcss.com/docs/border-radius
1788
+ */
1789
+ rounded: [{
1790
+ rounded: scaleRadius()
1791
+ }],
1792
+ /**
1793
+ * Border Radius Start
1794
+ * @see https://tailwindcss.com/docs/border-radius
1795
+ */
1796
+ "rounded-s": [{
1797
+ "rounded-s": scaleRadius()
1798
+ }],
1799
+ /**
1800
+ * Border Radius End
1801
+ * @see https://tailwindcss.com/docs/border-radius
1802
+ */
1803
+ "rounded-e": [{
1804
+ "rounded-e": scaleRadius()
1805
+ }],
1806
+ /**
1807
+ * Border Radius Top
1808
+ * @see https://tailwindcss.com/docs/border-radius
1809
+ */
1810
+ "rounded-t": [{
1811
+ "rounded-t": scaleRadius()
1812
+ }],
1813
+ /**
1814
+ * Border Radius Right
1815
+ * @see https://tailwindcss.com/docs/border-radius
1816
+ */
1817
+ "rounded-r": [{
1818
+ "rounded-r": scaleRadius()
1819
+ }],
1820
+ /**
1821
+ * Border Radius Bottom
1822
+ * @see https://tailwindcss.com/docs/border-radius
1823
+ */
1824
+ "rounded-b": [{
1825
+ "rounded-b": scaleRadius()
1826
+ }],
1827
+ /**
1828
+ * Border Radius Left
1829
+ * @see https://tailwindcss.com/docs/border-radius
1830
+ */
1831
+ "rounded-l": [{
1832
+ "rounded-l": scaleRadius()
1833
+ }],
1834
+ /**
1835
+ * Border Radius Start Start
1836
+ * @see https://tailwindcss.com/docs/border-radius
1837
+ */
1838
+ "rounded-ss": [{
1839
+ "rounded-ss": scaleRadius()
1840
+ }],
1841
+ /**
1842
+ * Border Radius Start End
1843
+ * @see https://tailwindcss.com/docs/border-radius
1844
+ */
1845
+ "rounded-se": [{
1846
+ "rounded-se": scaleRadius()
1847
+ }],
1848
+ /**
1849
+ * Border Radius End End
1850
+ * @see https://tailwindcss.com/docs/border-radius
1851
+ */
1852
+ "rounded-ee": [{
1853
+ "rounded-ee": scaleRadius()
1854
+ }],
1855
+ /**
1856
+ * Border Radius End Start
1857
+ * @see https://tailwindcss.com/docs/border-radius
1858
+ */
1859
+ "rounded-es": [{
1860
+ "rounded-es": scaleRadius()
1861
+ }],
1862
+ /**
1863
+ * Border Radius Top Left
1864
+ * @see https://tailwindcss.com/docs/border-radius
1865
+ */
1866
+ "rounded-tl": [{
1867
+ "rounded-tl": scaleRadius()
1868
+ }],
1869
+ /**
1870
+ * Border Radius Top Right
1871
+ * @see https://tailwindcss.com/docs/border-radius
1872
+ */
1873
+ "rounded-tr": [{
1874
+ "rounded-tr": scaleRadius()
1875
+ }],
1876
+ /**
1877
+ * Border Radius Bottom Right
1878
+ * @see https://tailwindcss.com/docs/border-radius
1879
+ */
1880
+ "rounded-br": [{
1881
+ "rounded-br": scaleRadius()
1882
+ }],
1883
+ /**
1884
+ * Border Radius Bottom Left
1885
+ * @see https://tailwindcss.com/docs/border-radius
1886
+ */
1887
+ "rounded-bl": [{
1888
+ "rounded-bl": scaleRadius()
1889
+ }],
1890
+ /**
1891
+ * Border Width
1892
+ * @see https://tailwindcss.com/docs/border-width
1893
+ */
1894
+ "border-w": [{
1895
+ border: scaleBorderWidth()
1896
+ }],
1897
+ /**
1898
+ * Border Width Inline
1899
+ * @see https://tailwindcss.com/docs/border-width
1900
+ */
1901
+ "border-w-x": [{
1902
+ "border-x": scaleBorderWidth()
1903
+ }],
1904
+ /**
1905
+ * Border Width Block
1906
+ * @see https://tailwindcss.com/docs/border-width
1907
+ */
1908
+ "border-w-y": [{
1909
+ "border-y": scaleBorderWidth()
1910
+ }],
1911
+ /**
1912
+ * Border Width Inline Start
1913
+ * @see https://tailwindcss.com/docs/border-width
1914
+ */
1915
+ "border-w-s": [{
1916
+ "border-s": scaleBorderWidth()
1917
+ }],
1918
+ /**
1919
+ * Border Width Inline End
1920
+ * @see https://tailwindcss.com/docs/border-width
1921
+ */
1922
+ "border-w-e": [{
1923
+ "border-e": scaleBorderWidth()
1924
+ }],
1925
+ /**
1926
+ * Border Width Block Start
1927
+ * @see https://tailwindcss.com/docs/border-width
1928
+ */
1929
+ "border-w-bs": [{
1930
+ "border-bs": scaleBorderWidth()
1931
+ }],
1932
+ /**
1933
+ * Border Width Block End
1934
+ * @see https://tailwindcss.com/docs/border-width
1935
+ */
1936
+ "border-w-be": [{
1937
+ "border-be": scaleBorderWidth()
1938
+ }],
1939
+ /**
1940
+ * Border Width Top
1941
+ * @see https://tailwindcss.com/docs/border-width
1942
+ */
1943
+ "border-w-t": [{
1944
+ "border-t": scaleBorderWidth()
1945
+ }],
1946
+ /**
1947
+ * Border Width Right
1948
+ * @see https://tailwindcss.com/docs/border-width
1949
+ */
1950
+ "border-w-r": [{
1951
+ "border-r": scaleBorderWidth()
1952
+ }],
1953
+ /**
1954
+ * Border Width Bottom
1955
+ * @see https://tailwindcss.com/docs/border-width
1956
+ */
1957
+ "border-w-b": [{
1958
+ "border-b": scaleBorderWidth()
1959
+ }],
1960
+ /**
1961
+ * Border Width Left
1962
+ * @see https://tailwindcss.com/docs/border-width
1963
+ */
1964
+ "border-w-l": [{
1965
+ "border-l": scaleBorderWidth()
1966
+ }],
1967
+ /**
1968
+ * Divide Width X
1969
+ * @see https://tailwindcss.com/docs/border-width#between-children
1970
+ */
1971
+ "divide-x": [{
1972
+ "divide-x": scaleBorderWidth()
1973
+ }],
1974
+ /**
1975
+ * Divide Width X Reverse
1976
+ * @see https://tailwindcss.com/docs/border-width#between-children
1977
+ */
1978
+ "divide-x-reverse": ["divide-x-reverse"],
1979
+ /**
1980
+ * Divide Width Y
1981
+ * @see https://tailwindcss.com/docs/border-width#between-children
1982
+ */
1983
+ "divide-y": [{
1984
+ "divide-y": scaleBorderWidth()
1985
+ }],
1986
+ /**
1987
+ * Divide Width Y Reverse
1988
+ * @see https://tailwindcss.com/docs/border-width#between-children
1989
+ */
1990
+ "divide-y-reverse": ["divide-y-reverse"],
1991
+ /**
1992
+ * Border Style
1993
+ * @see https://tailwindcss.com/docs/border-style
1994
+ */
1995
+ "border-style": [{
1996
+ border: [...scaleLineStyle(), "hidden", "none"]
1997
+ }],
1998
+ /**
1999
+ * Divide Style
2000
+ * @see https://tailwindcss.com/docs/border-style#setting-the-divider-style
2001
+ */
2002
+ "divide-style": [{
2003
+ divide: [...scaleLineStyle(), "hidden", "none"]
2004
+ }],
2005
+ /**
2006
+ * Border Color
2007
+ * @see https://tailwindcss.com/docs/border-color
2008
+ */
2009
+ "border-color": [{
2010
+ border: scaleColor()
2011
+ }],
2012
+ /**
2013
+ * Border Color Inline
2014
+ * @see https://tailwindcss.com/docs/border-color
2015
+ */
2016
+ "border-color-x": [{
2017
+ "border-x": scaleColor()
2018
+ }],
2019
+ /**
2020
+ * Border Color Block
2021
+ * @see https://tailwindcss.com/docs/border-color
2022
+ */
2023
+ "border-color-y": [{
2024
+ "border-y": scaleColor()
2025
+ }],
2026
+ /**
2027
+ * Border Color Inline Start
2028
+ * @see https://tailwindcss.com/docs/border-color
2029
+ */
2030
+ "border-color-s": [{
2031
+ "border-s": scaleColor()
2032
+ }],
2033
+ /**
2034
+ * Border Color Inline End
2035
+ * @see https://tailwindcss.com/docs/border-color
2036
+ */
2037
+ "border-color-e": [{
2038
+ "border-e": scaleColor()
2039
+ }],
2040
+ /**
2041
+ * Border Color Block Start
2042
+ * @see https://tailwindcss.com/docs/border-color
2043
+ */
2044
+ "border-color-bs": [{
2045
+ "border-bs": scaleColor()
2046
+ }],
2047
+ /**
2048
+ * Border Color Block End
2049
+ * @see https://tailwindcss.com/docs/border-color
2050
+ */
2051
+ "border-color-be": [{
2052
+ "border-be": scaleColor()
2053
+ }],
2054
+ /**
2055
+ * Border Color Top
2056
+ * @see https://tailwindcss.com/docs/border-color
2057
+ */
2058
+ "border-color-t": [{
2059
+ "border-t": scaleColor()
2060
+ }],
2061
+ /**
2062
+ * Border Color Right
2063
+ * @see https://tailwindcss.com/docs/border-color
2064
+ */
2065
+ "border-color-r": [{
2066
+ "border-r": scaleColor()
2067
+ }],
2068
+ /**
2069
+ * Border Color Bottom
2070
+ * @see https://tailwindcss.com/docs/border-color
2071
+ */
2072
+ "border-color-b": [{
2073
+ "border-b": scaleColor()
2074
+ }],
2075
+ /**
2076
+ * Border Color Left
2077
+ * @see https://tailwindcss.com/docs/border-color
2078
+ */
2079
+ "border-color-l": [{
2080
+ "border-l": scaleColor()
2081
+ }],
2082
+ /**
2083
+ * Divide Color
2084
+ * @see https://tailwindcss.com/docs/divide-color
2085
+ */
2086
+ "divide-color": [{
2087
+ divide: scaleColor()
2088
+ }],
2089
+ /**
2090
+ * Outline Style
2091
+ * @see https://tailwindcss.com/docs/outline-style
2092
+ */
2093
+ "outline-style": [{
2094
+ outline: [...scaleLineStyle(), "none", "hidden"]
2095
+ }],
2096
+ /**
2097
+ * Outline Offset
2098
+ * @see https://tailwindcss.com/docs/outline-offset
2099
+ */
2100
+ "outline-offset": [{
2101
+ "outline-offset": [isNumber, isArbitraryVariable, isArbitraryValue]
2102
+ }],
2103
+ /**
2104
+ * Outline Width
2105
+ * @see https://tailwindcss.com/docs/outline-width
2106
+ */
2107
+ "outline-w": [{
2108
+ outline: ["", isNumber, isArbitraryVariableLength, isArbitraryLength]
2109
+ }],
2110
+ /**
2111
+ * Outline Color
2112
+ * @see https://tailwindcss.com/docs/outline-color
2113
+ */
2114
+ "outline-color": [{
2115
+ outline: scaleColor()
2116
+ }],
2117
+ // ---------------
2118
+ // --- Effects ---
2119
+ // ---------------
2120
+ /**
2121
+ * Box Shadow
2122
+ * @see https://tailwindcss.com/docs/box-shadow
2123
+ */
2124
+ shadow: [{
2125
+ shadow: [
2126
+ // Deprecated since Tailwind CSS v4.0.0
2127
+ "",
2128
+ "none",
2129
+ themeShadow,
2130
+ isArbitraryVariableShadow,
2131
+ isArbitraryShadow
2132
+ ]
2133
+ }],
2134
+ /**
2135
+ * Box Shadow Color
2136
+ * @see https://tailwindcss.com/docs/box-shadow#setting-the-shadow-color
2137
+ */
2138
+ "shadow-color": [{
2139
+ shadow: scaleColor()
2140
+ }],
2141
+ /**
2142
+ * Inset Box Shadow
2143
+ * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-shadow
2144
+ */
2145
+ "inset-shadow": [{
2146
+ "inset-shadow": ["none", themeInsetShadow, isArbitraryVariableShadow, isArbitraryShadow]
2147
+ }],
2148
+ /**
2149
+ * Inset Box Shadow Color
2150
+ * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-shadow-color
2151
+ */
2152
+ "inset-shadow-color": [{
2153
+ "inset-shadow": scaleColor()
2154
+ }],
2155
+ /**
2156
+ * Ring Width
2157
+ * @see https://tailwindcss.com/docs/box-shadow#adding-a-ring
2158
+ */
2159
+ "ring-w": [{
2160
+ ring: scaleBorderWidth()
2161
+ }],
2162
+ /**
2163
+ * Ring Width Inset
2164
+ * @see https://v3.tailwindcss.com/docs/ring-width#inset-rings
2165
+ * @deprecated since Tailwind CSS v4.0.0
2166
+ * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
2167
+ */
2168
+ "ring-w-inset": ["ring-inset"],
2169
+ /**
2170
+ * Ring Color
2171
+ * @see https://tailwindcss.com/docs/box-shadow#setting-the-ring-color
2172
+ */
2173
+ "ring-color": [{
2174
+ ring: scaleColor()
2175
+ }],
2176
+ /**
2177
+ * Ring Offset Width
2178
+ * @see https://v3.tailwindcss.com/docs/ring-offset-width
2179
+ * @deprecated since Tailwind CSS v4.0.0
2180
+ * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
2181
+ */
2182
+ "ring-offset-w": [{
2183
+ "ring-offset": [isNumber, isArbitraryLength]
2184
+ }],
2185
+ /**
2186
+ * Ring Offset Color
2187
+ * @see https://v3.tailwindcss.com/docs/ring-offset-color
2188
+ * @deprecated since Tailwind CSS v4.0.0
2189
+ * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
2190
+ */
2191
+ "ring-offset-color": [{
2192
+ "ring-offset": scaleColor()
2193
+ }],
2194
+ /**
2195
+ * Inset Ring Width
2196
+ * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-ring
2197
+ */
2198
+ "inset-ring-w": [{
2199
+ "inset-ring": scaleBorderWidth()
2200
+ }],
2201
+ /**
2202
+ * Inset Ring Color
2203
+ * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-ring-color
2204
+ */
2205
+ "inset-ring-color": [{
2206
+ "inset-ring": scaleColor()
2207
+ }],
2208
+ /**
2209
+ * Text Shadow
2210
+ * @see https://tailwindcss.com/docs/text-shadow
2211
+ */
2212
+ "text-shadow": [{
2213
+ "text-shadow": ["none", themeTextShadow, isArbitraryVariableShadow, isArbitraryShadow]
2214
+ }],
2215
+ /**
2216
+ * Text Shadow Color
2217
+ * @see https://tailwindcss.com/docs/text-shadow#setting-the-shadow-color
2218
+ */
2219
+ "text-shadow-color": [{
2220
+ "text-shadow": scaleColor()
2221
+ }],
2222
+ /**
2223
+ * Opacity
2224
+ * @see https://tailwindcss.com/docs/opacity
2225
+ */
2226
+ opacity: [{
2227
+ opacity: [isNumber, isArbitraryVariable, isArbitraryValue]
2228
+ }],
2229
+ /**
2230
+ * Mix Blend Mode
2231
+ * @see https://tailwindcss.com/docs/mix-blend-mode
2232
+ */
2233
+ "mix-blend": [{
2234
+ "mix-blend": [...scaleBlendMode(), "plus-darker", "plus-lighter"]
2235
+ }],
2236
+ /**
2237
+ * Background Blend Mode
2238
+ * @see https://tailwindcss.com/docs/background-blend-mode
2239
+ */
2240
+ "bg-blend": [{
2241
+ "bg-blend": scaleBlendMode()
2242
+ }],
2243
+ /**
2244
+ * Mask Clip
2245
+ * @see https://tailwindcss.com/docs/mask-clip
2246
+ */
2247
+ "mask-clip": [{
2248
+ "mask-clip": ["border", "padding", "content", "fill", "stroke", "view"]
2249
+ }, "mask-no-clip"],
2250
+ /**
2251
+ * Mask Composite
2252
+ * @see https://tailwindcss.com/docs/mask-composite
2253
+ */
2254
+ "mask-composite": [{
2255
+ mask: ["add", "subtract", "intersect", "exclude"]
2256
+ }],
2257
+ /**
2258
+ * Mask Image
2259
+ * @see https://tailwindcss.com/docs/mask-image
2260
+ */
2261
+ "mask-image-linear-pos": [{
2262
+ "mask-linear": [isNumber]
2263
+ }],
2264
+ "mask-image-linear-from-pos": [{
2265
+ "mask-linear-from": scaleMaskImagePosition()
2266
+ }],
2267
+ "mask-image-linear-to-pos": [{
2268
+ "mask-linear-to": scaleMaskImagePosition()
2269
+ }],
2270
+ "mask-image-linear-from-color": [{
2271
+ "mask-linear-from": scaleColor()
2272
+ }],
2273
+ "mask-image-linear-to-color": [{
2274
+ "mask-linear-to": scaleColor()
2275
+ }],
2276
+ "mask-image-t-from-pos": [{
2277
+ "mask-t-from": scaleMaskImagePosition()
2278
+ }],
2279
+ "mask-image-t-to-pos": [{
2280
+ "mask-t-to": scaleMaskImagePosition()
2281
+ }],
2282
+ "mask-image-t-from-color": [{
2283
+ "mask-t-from": scaleColor()
2284
+ }],
2285
+ "mask-image-t-to-color": [{
2286
+ "mask-t-to": scaleColor()
2287
+ }],
2288
+ "mask-image-r-from-pos": [{
2289
+ "mask-r-from": scaleMaskImagePosition()
2290
+ }],
2291
+ "mask-image-r-to-pos": [{
2292
+ "mask-r-to": scaleMaskImagePosition()
2293
+ }],
2294
+ "mask-image-r-from-color": [{
2295
+ "mask-r-from": scaleColor()
2296
+ }],
2297
+ "mask-image-r-to-color": [{
2298
+ "mask-r-to": scaleColor()
2299
+ }],
2300
+ "mask-image-b-from-pos": [{
2301
+ "mask-b-from": scaleMaskImagePosition()
2302
+ }],
2303
+ "mask-image-b-to-pos": [{
2304
+ "mask-b-to": scaleMaskImagePosition()
2305
+ }],
2306
+ "mask-image-b-from-color": [{
2307
+ "mask-b-from": scaleColor()
2308
+ }],
2309
+ "mask-image-b-to-color": [{
2310
+ "mask-b-to": scaleColor()
2311
+ }],
2312
+ "mask-image-l-from-pos": [{
2313
+ "mask-l-from": scaleMaskImagePosition()
2314
+ }],
2315
+ "mask-image-l-to-pos": [{
2316
+ "mask-l-to": scaleMaskImagePosition()
2317
+ }],
2318
+ "mask-image-l-from-color": [{
2319
+ "mask-l-from": scaleColor()
2320
+ }],
2321
+ "mask-image-l-to-color": [{
2322
+ "mask-l-to": scaleColor()
2323
+ }],
2324
+ "mask-image-x-from-pos": [{
2325
+ "mask-x-from": scaleMaskImagePosition()
2326
+ }],
2327
+ "mask-image-x-to-pos": [{
2328
+ "mask-x-to": scaleMaskImagePosition()
2329
+ }],
2330
+ "mask-image-x-from-color": [{
2331
+ "mask-x-from": scaleColor()
2332
+ }],
2333
+ "mask-image-x-to-color": [{
2334
+ "mask-x-to": scaleColor()
2335
+ }],
2336
+ "mask-image-y-from-pos": [{
2337
+ "mask-y-from": scaleMaskImagePosition()
2338
+ }],
2339
+ "mask-image-y-to-pos": [{
2340
+ "mask-y-to": scaleMaskImagePosition()
2341
+ }],
2342
+ "mask-image-y-from-color": [{
2343
+ "mask-y-from": scaleColor()
2344
+ }],
2345
+ "mask-image-y-to-color": [{
2346
+ "mask-y-to": scaleColor()
2347
+ }],
2348
+ "mask-image-radial": [{
2349
+ "mask-radial": [isArbitraryVariable, isArbitraryValue]
2350
+ }],
2351
+ "mask-image-radial-from-pos": [{
2352
+ "mask-radial-from": scaleMaskImagePosition()
2353
+ }],
2354
+ "mask-image-radial-to-pos": [{
2355
+ "mask-radial-to": scaleMaskImagePosition()
2356
+ }],
2357
+ "mask-image-radial-from-color": [{
2358
+ "mask-radial-from": scaleColor()
2359
+ }],
2360
+ "mask-image-radial-to-color": [{
2361
+ "mask-radial-to": scaleColor()
2362
+ }],
2363
+ "mask-image-radial-shape": [{
2364
+ "mask-radial": ["circle", "ellipse"]
2365
+ }],
2366
+ "mask-image-radial-size": [{
2367
+ "mask-radial": [{
2368
+ closest: ["side", "corner"],
2369
+ farthest: ["side", "corner"]
2370
+ }]
2371
+ }],
2372
+ "mask-image-radial-pos": [{
2373
+ "mask-radial-at": scalePosition()
2374
+ }],
2375
+ "mask-image-conic-pos": [{
2376
+ "mask-conic": [isNumber]
2377
+ }],
2378
+ "mask-image-conic-from-pos": [{
2379
+ "mask-conic-from": scaleMaskImagePosition()
2380
+ }],
2381
+ "mask-image-conic-to-pos": [{
2382
+ "mask-conic-to": scaleMaskImagePosition()
2383
+ }],
2384
+ "mask-image-conic-from-color": [{
2385
+ "mask-conic-from": scaleColor()
2386
+ }],
2387
+ "mask-image-conic-to-color": [{
2388
+ "mask-conic-to": scaleColor()
2389
+ }],
2390
+ /**
2391
+ * Mask Mode
2392
+ * @see https://tailwindcss.com/docs/mask-mode
2393
+ */
2394
+ "mask-mode": [{
2395
+ mask: ["alpha", "luminance", "match"]
2396
+ }],
2397
+ /**
2398
+ * Mask Origin
2399
+ * @see https://tailwindcss.com/docs/mask-origin
2400
+ */
2401
+ "mask-origin": [{
2402
+ "mask-origin": ["border", "padding", "content", "fill", "stroke", "view"]
2403
+ }],
2404
+ /**
2405
+ * Mask Position
2406
+ * @see https://tailwindcss.com/docs/mask-position
2407
+ */
2408
+ "mask-position": [{
2409
+ mask: scaleBgPosition()
2410
+ }],
2411
+ /**
2412
+ * Mask Repeat
2413
+ * @see https://tailwindcss.com/docs/mask-repeat
2414
+ */
2415
+ "mask-repeat": [{
2416
+ mask: scaleBgRepeat()
2417
+ }],
2418
+ /**
2419
+ * Mask Size
2420
+ * @see https://tailwindcss.com/docs/mask-size
2421
+ */
2422
+ "mask-size": [{
2423
+ mask: scaleBgSize()
2424
+ }],
2425
+ /**
2426
+ * Mask Type
2427
+ * @see https://tailwindcss.com/docs/mask-type
2428
+ */
2429
+ "mask-type": [{
2430
+ "mask-type": ["alpha", "luminance"]
2431
+ }],
2432
+ /**
2433
+ * Mask Image
2434
+ * @see https://tailwindcss.com/docs/mask-image
2435
+ */
2436
+ "mask-image": [{
2437
+ mask: ["none", isArbitraryVariable, isArbitraryValue]
2438
+ }],
2439
+ // ---------------
2440
+ // --- Filters ---
2441
+ // ---------------
2442
+ /**
2443
+ * Filter
2444
+ * @see https://tailwindcss.com/docs/filter
2445
+ */
2446
+ filter: [{
2447
+ filter: [
2448
+ // Deprecated since Tailwind CSS v3.0.0
2449
+ "",
2450
+ "none",
2451
+ isArbitraryVariable,
2452
+ isArbitraryValue
2453
+ ]
2454
+ }],
2455
+ /**
2456
+ * Blur
2457
+ * @see https://tailwindcss.com/docs/blur
2458
+ */
2459
+ blur: [{
2460
+ blur: scaleBlur()
2461
+ }],
2462
+ /**
2463
+ * Brightness
2464
+ * @see https://tailwindcss.com/docs/brightness
2465
+ */
2466
+ brightness: [{
2467
+ brightness: [isNumber, isArbitraryVariable, isArbitraryValue]
2468
+ }],
2469
+ /**
2470
+ * Contrast
2471
+ * @see https://tailwindcss.com/docs/contrast
2472
+ */
2473
+ contrast: [{
2474
+ contrast: [isNumber, isArbitraryVariable, isArbitraryValue]
2475
+ }],
2476
+ /**
2477
+ * Drop Shadow
2478
+ * @see https://tailwindcss.com/docs/drop-shadow
2479
+ */
2480
+ "drop-shadow": [{
2481
+ "drop-shadow": [
2482
+ // Deprecated since Tailwind CSS v4.0.0
2483
+ "",
2484
+ "none",
2485
+ themeDropShadow,
2486
+ isArbitraryVariableShadow,
2487
+ isArbitraryShadow
2488
+ ]
2489
+ }],
2490
+ /**
2491
+ * Drop Shadow Color
2492
+ * @see https://tailwindcss.com/docs/filter-drop-shadow#setting-the-shadow-color
2493
+ */
2494
+ "drop-shadow-color": [{
2495
+ "drop-shadow": scaleColor()
2496
+ }],
2497
+ /**
2498
+ * Grayscale
2499
+ * @see https://tailwindcss.com/docs/grayscale
2500
+ */
2501
+ grayscale: [{
2502
+ grayscale: ["", isNumber, isArbitraryVariable, isArbitraryValue]
2503
+ }],
2504
+ /**
2505
+ * Hue Rotate
2506
+ * @see https://tailwindcss.com/docs/hue-rotate
2507
+ */
2508
+ "hue-rotate": [{
2509
+ "hue-rotate": [isNumber, isArbitraryVariable, isArbitraryValue]
2510
+ }],
2511
+ /**
2512
+ * Invert
2513
+ * @see https://tailwindcss.com/docs/invert
2514
+ */
2515
+ invert: [{
2516
+ invert: ["", isNumber, isArbitraryVariable, isArbitraryValue]
2517
+ }],
2518
+ /**
2519
+ * Saturate
2520
+ * @see https://tailwindcss.com/docs/saturate
2521
+ */
2522
+ saturate: [{
2523
+ saturate: [isNumber, isArbitraryVariable, isArbitraryValue]
2524
+ }],
2525
+ /**
2526
+ * Sepia
2527
+ * @see https://tailwindcss.com/docs/sepia
2528
+ */
2529
+ sepia: [{
2530
+ sepia: ["", isNumber, isArbitraryVariable, isArbitraryValue]
2531
+ }],
2532
+ /**
2533
+ * Backdrop Filter
2534
+ * @see https://tailwindcss.com/docs/backdrop-filter
2535
+ */
2536
+ "backdrop-filter": [{
2537
+ "backdrop-filter": [
2538
+ // Deprecated since Tailwind CSS v3.0.0
2539
+ "",
2540
+ "none",
2541
+ isArbitraryVariable,
2542
+ isArbitraryValue
2543
+ ]
2544
+ }],
2545
+ /**
2546
+ * Backdrop Blur
2547
+ * @see https://tailwindcss.com/docs/backdrop-blur
2548
+ */
2549
+ "backdrop-blur": [{
2550
+ "backdrop-blur": scaleBlur()
2551
+ }],
2552
+ /**
2553
+ * Backdrop Brightness
2554
+ * @see https://tailwindcss.com/docs/backdrop-brightness
2555
+ */
2556
+ "backdrop-brightness": [{
2557
+ "backdrop-brightness": [isNumber, isArbitraryVariable, isArbitraryValue]
2558
+ }],
2559
+ /**
2560
+ * Backdrop Contrast
2561
+ * @see https://tailwindcss.com/docs/backdrop-contrast
2562
+ */
2563
+ "backdrop-contrast": [{
2564
+ "backdrop-contrast": [isNumber, isArbitraryVariable, isArbitraryValue]
2565
+ }],
2566
+ /**
2567
+ * Backdrop Grayscale
2568
+ * @see https://tailwindcss.com/docs/backdrop-grayscale
2569
+ */
2570
+ "backdrop-grayscale": [{
2571
+ "backdrop-grayscale": ["", isNumber, isArbitraryVariable, isArbitraryValue]
2572
+ }],
2573
+ /**
2574
+ * Backdrop Hue Rotate
2575
+ * @see https://tailwindcss.com/docs/backdrop-hue-rotate
2576
+ */
2577
+ "backdrop-hue-rotate": [{
2578
+ "backdrop-hue-rotate": [isNumber, isArbitraryVariable, isArbitraryValue]
2579
+ }],
2580
+ /**
2581
+ * Backdrop Invert
2582
+ * @see https://tailwindcss.com/docs/backdrop-invert
2583
+ */
2584
+ "backdrop-invert": [{
2585
+ "backdrop-invert": ["", isNumber, isArbitraryVariable, isArbitraryValue]
2586
+ }],
2587
+ /**
2588
+ * Backdrop Opacity
2589
+ * @see https://tailwindcss.com/docs/backdrop-opacity
2590
+ */
2591
+ "backdrop-opacity": [{
2592
+ "backdrop-opacity": [isNumber, isArbitraryVariable, isArbitraryValue]
2593
+ }],
2594
+ /**
2595
+ * Backdrop Saturate
2596
+ * @see https://tailwindcss.com/docs/backdrop-saturate
2597
+ */
2598
+ "backdrop-saturate": [{
2599
+ "backdrop-saturate": [isNumber, isArbitraryVariable, isArbitraryValue]
2600
+ }],
2601
+ /**
2602
+ * Backdrop Sepia
2603
+ * @see https://tailwindcss.com/docs/backdrop-sepia
2604
+ */
2605
+ "backdrop-sepia": [{
2606
+ "backdrop-sepia": ["", isNumber, isArbitraryVariable, isArbitraryValue]
2607
+ }],
2608
+ // --------------
2609
+ // --- Tables ---
2610
+ // --------------
2611
+ /**
2612
+ * Border Collapse
2613
+ * @see https://tailwindcss.com/docs/border-collapse
2614
+ */
2615
+ "border-collapse": [{
2616
+ border: ["collapse", "separate"]
2617
+ }],
2618
+ /**
2619
+ * Border Spacing
2620
+ * @see https://tailwindcss.com/docs/border-spacing
2621
+ */
2622
+ "border-spacing": [{
2623
+ "border-spacing": scaleUnambiguousSpacing()
2624
+ }],
2625
+ /**
2626
+ * Border Spacing X
2627
+ * @see https://tailwindcss.com/docs/border-spacing
2628
+ */
2629
+ "border-spacing-x": [{
2630
+ "border-spacing-x": scaleUnambiguousSpacing()
2631
+ }],
2632
+ /**
2633
+ * Border Spacing Y
2634
+ * @see https://tailwindcss.com/docs/border-spacing
2635
+ */
2636
+ "border-spacing-y": [{
2637
+ "border-spacing-y": scaleUnambiguousSpacing()
2638
+ }],
2639
+ /**
2640
+ * Table Layout
2641
+ * @see https://tailwindcss.com/docs/table-layout
2642
+ */
2643
+ "table-layout": [{
2644
+ table: ["auto", "fixed"]
2645
+ }],
2646
+ /**
2647
+ * Caption Side
2648
+ * @see https://tailwindcss.com/docs/caption-side
2649
+ */
2650
+ caption: [{
2651
+ caption: ["top", "bottom"]
2652
+ }],
2653
+ // ---------------------------------
2654
+ // --- Transitions and Animation ---
2655
+ // ---------------------------------
2656
+ /**
2657
+ * Transition Property
2658
+ * @see https://tailwindcss.com/docs/transition-property
2659
+ */
2660
+ transition: [{
2661
+ transition: ["", "all", "colors", "opacity", "shadow", "transform", "none", isArbitraryVariable, isArbitraryValue]
2662
+ }],
2663
+ /**
2664
+ * Transition Behavior
2665
+ * @see https://tailwindcss.com/docs/transition-behavior
2666
+ */
2667
+ "transition-behavior": [{
2668
+ transition: ["normal", "discrete"]
2669
+ }],
2670
+ /**
2671
+ * Transition Duration
2672
+ * @see https://tailwindcss.com/docs/transition-duration
2673
+ */
2674
+ duration: [{
2675
+ duration: [isNumber, "initial", isArbitraryVariable, isArbitraryValue]
2676
+ }],
2677
+ /**
2678
+ * Transition Timing Function
2679
+ * @see https://tailwindcss.com/docs/transition-timing-function
2680
+ */
2681
+ ease: [{
2682
+ ease: ["linear", "initial", themeEase, isArbitraryVariable, isArbitraryValue]
2683
+ }],
2684
+ /**
2685
+ * Transition Delay
2686
+ * @see https://tailwindcss.com/docs/transition-delay
2687
+ */
2688
+ delay: [{
2689
+ delay: [isNumber, isArbitraryVariable, isArbitraryValue]
2690
+ }],
2691
+ /**
2692
+ * Animation
2693
+ * @see https://tailwindcss.com/docs/animation
2694
+ */
2695
+ animate: [{
2696
+ animate: ["none", themeAnimate, isArbitraryVariable, isArbitraryValue]
2697
+ }],
2698
+ // ------------------
2699
+ // --- Transforms ---
2700
+ // ------------------
2701
+ /**
2702
+ * Backface Visibility
2703
+ * @see https://tailwindcss.com/docs/backface-visibility
2704
+ */
2705
+ backface: [{
2706
+ backface: ["hidden", "visible"]
2707
+ }],
2708
+ /**
2709
+ * Perspective
2710
+ * @see https://tailwindcss.com/docs/perspective
2711
+ */
2712
+ perspective: [{
2713
+ perspective: [themePerspective, isArbitraryVariable, isArbitraryValue]
2714
+ }],
2715
+ /**
2716
+ * Perspective Origin
2717
+ * @see https://tailwindcss.com/docs/perspective-origin
2718
+ */
2719
+ "perspective-origin": [{
2720
+ "perspective-origin": scalePositionWithArbitrary()
2721
+ }],
2722
+ /**
2723
+ * Rotate
2724
+ * @see https://tailwindcss.com/docs/rotate
2725
+ */
2726
+ rotate: [{
2727
+ rotate: scaleRotate()
2728
+ }],
2729
+ /**
2730
+ * Rotate X
2731
+ * @see https://tailwindcss.com/docs/rotate
2732
+ */
2733
+ "rotate-x": [{
2734
+ "rotate-x": scaleRotate()
2735
+ }],
2736
+ /**
2737
+ * Rotate Y
2738
+ * @see https://tailwindcss.com/docs/rotate
2739
+ */
2740
+ "rotate-y": [{
2741
+ "rotate-y": scaleRotate()
2742
+ }],
2743
+ /**
2744
+ * Rotate Z
2745
+ * @see https://tailwindcss.com/docs/rotate
2746
+ */
2747
+ "rotate-z": [{
2748
+ "rotate-z": scaleRotate()
2749
+ }],
2750
+ /**
2751
+ * Scale
2752
+ * @see https://tailwindcss.com/docs/scale
2753
+ */
2754
+ scale: [{
2755
+ scale: scaleScale()
2756
+ }],
2757
+ /**
2758
+ * Scale X
2759
+ * @see https://tailwindcss.com/docs/scale
2760
+ */
2761
+ "scale-x": [{
2762
+ "scale-x": scaleScale()
2763
+ }],
2764
+ /**
2765
+ * Scale Y
2766
+ * @see https://tailwindcss.com/docs/scale
2767
+ */
2768
+ "scale-y": [{
2769
+ "scale-y": scaleScale()
2770
+ }],
2771
+ /**
2772
+ * Scale Z
2773
+ * @see https://tailwindcss.com/docs/scale
2774
+ */
2775
+ "scale-z": [{
2776
+ "scale-z": scaleScale()
2777
+ }],
2778
+ /**
2779
+ * Scale 3D
2780
+ * @see https://tailwindcss.com/docs/scale
2781
+ */
2782
+ "scale-3d": ["scale-3d"],
2783
+ /**
2784
+ * Skew
2785
+ * @see https://tailwindcss.com/docs/skew
2786
+ */
2787
+ skew: [{
2788
+ skew: scaleSkew()
2789
+ }],
2790
+ /**
2791
+ * Skew X
2792
+ * @see https://tailwindcss.com/docs/skew
2793
+ */
2794
+ "skew-x": [{
2795
+ "skew-x": scaleSkew()
2796
+ }],
2797
+ /**
2798
+ * Skew Y
2799
+ * @see https://tailwindcss.com/docs/skew
2800
+ */
2801
+ "skew-y": [{
2802
+ "skew-y": scaleSkew()
2803
+ }],
2804
+ /**
2805
+ * Transform
2806
+ * @see https://tailwindcss.com/docs/transform
2807
+ */
2808
+ transform: [{
2809
+ transform: [isArbitraryVariable, isArbitraryValue, "", "none", "gpu", "cpu"]
2810
+ }],
2811
+ /**
2812
+ * Transform Origin
2813
+ * @see https://tailwindcss.com/docs/transform-origin
2814
+ */
2815
+ "transform-origin": [{
2816
+ origin: scalePositionWithArbitrary()
2817
+ }],
2818
+ /**
2819
+ * Transform Style
2820
+ * @see https://tailwindcss.com/docs/transform-style
2821
+ */
2822
+ "transform-style": [{
2823
+ transform: ["3d", "flat"]
2824
+ }],
2825
+ /**
2826
+ * Translate
2827
+ * @see https://tailwindcss.com/docs/translate
2828
+ */
2829
+ translate: [{
2830
+ translate: scaleTranslate()
2831
+ }],
2832
+ /**
2833
+ * Translate X
2834
+ * @see https://tailwindcss.com/docs/translate
2835
+ */
2836
+ "translate-x": [{
2837
+ "translate-x": scaleTranslate()
2838
+ }],
2839
+ /**
2840
+ * Translate Y
2841
+ * @see https://tailwindcss.com/docs/translate
2842
+ */
2843
+ "translate-y": [{
2844
+ "translate-y": scaleTranslate()
2845
+ }],
2846
+ /**
2847
+ * Translate Z
2848
+ * @see https://tailwindcss.com/docs/translate
2849
+ */
2850
+ "translate-z": [{
2851
+ "translate-z": scaleTranslate()
2852
+ }],
2853
+ /**
2854
+ * Translate None
2855
+ * @see https://tailwindcss.com/docs/translate
2856
+ */
2857
+ "translate-none": ["translate-none"],
2858
+ /**
2859
+ * Zoom
2860
+ * @see https://tailwindcss.com/docs/zoom
2861
+ */
2862
+ zoom: [{
2863
+ zoom: [isInteger, isArbitraryVariable, isArbitraryValue]
2864
+ }],
2865
+ // ---------------------
2866
+ // --- Interactivity ---
2867
+ // ---------------------
2868
+ /**
2869
+ * Accent Color
2870
+ * @see https://tailwindcss.com/docs/accent-color
2871
+ */
2872
+ accent: [{
2873
+ accent: scaleColor()
2874
+ }],
2875
+ /**
2876
+ * Appearance
2877
+ * @see https://tailwindcss.com/docs/appearance
2878
+ */
2879
+ appearance: [{
2880
+ appearance: ["none", "auto"]
2881
+ }],
2882
+ /**
2883
+ * Caret Color
2884
+ * @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities
2885
+ */
2886
+ "caret-color": [{
2887
+ caret: scaleColor()
2888
+ }],
2889
+ /**
2890
+ * Color Scheme
2891
+ * @see https://tailwindcss.com/docs/color-scheme
2892
+ */
2893
+ "color-scheme": [{
2894
+ scheme: ["normal", "dark", "light", "light-dark", "only-dark", "only-light"]
2895
+ }],
2896
+ /**
2897
+ * Cursor
2898
+ * @see https://tailwindcss.com/docs/cursor
2899
+ */
2900
+ cursor: [{
2901
+ cursor: ["auto", "default", "pointer", "wait", "text", "move", "help", "not-allowed", "none", "context-menu", "progress", "cell", "crosshair", "vertical-text", "alias", "copy", "no-drop", "grab", "grabbing", "all-scroll", "col-resize", "row-resize", "n-resize", "e-resize", "s-resize", "w-resize", "ne-resize", "nw-resize", "se-resize", "sw-resize", "ew-resize", "ns-resize", "nesw-resize", "nwse-resize", "zoom-in", "zoom-out", isArbitraryVariable, isArbitraryValue]
2902
+ }],
2903
+ /**
2904
+ * Field Sizing
2905
+ * @see https://tailwindcss.com/docs/field-sizing
2906
+ */
2907
+ "field-sizing": [{
2908
+ "field-sizing": ["fixed", "content"]
2909
+ }],
2910
+ /**
2911
+ * Pointer Events
2912
+ * @see https://tailwindcss.com/docs/pointer-events
2913
+ */
2914
+ "pointer-events": [{
2915
+ "pointer-events": ["auto", "none"]
2916
+ }],
2917
+ /**
2918
+ * Resize
2919
+ * @see https://tailwindcss.com/docs/resize
2920
+ */
2921
+ resize: [{
2922
+ resize: ["none", "", "y", "x"]
2923
+ }],
2924
+ /**
2925
+ * Scroll Behavior
2926
+ * @see https://tailwindcss.com/docs/scroll-behavior
2927
+ */
2928
+ "scroll-behavior": [{
2929
+ scroll: ["auto", "smooth"]
2930
+ }],
2931
+ /**
2932
+ * Scrollbar Thumb Color
2933
+ * @see https://tailwindcss.com/docs/scrollbar-color
2934
+ */
2935
+ "scrollbar-thumb-color": [{
2936
+ "scrollbar-thumb": scaleColor()
2937
+ }],
2938
+ /**
2939
+ * Scrollbar Track Color
2940
+ * @see https://tailwindcss.com/docs/scrollbar-color
2941
+ */
2942
+ "scrollbar-track-color": [{
2943
+ "scrollbar-track": scaleColor()
2944
+ }],
2945
+ /**
2946
+ * Scrollbar Gutter
2947
+ * @see https://tailwindcss.com/docs/scrollbar-gutter
2948
+ */
2949
+ "scrollbar-gutter": [{
2950
+ "scrollbar-gutter": ["auto", "stable", "both"]
2951
+ }],
2952
+ /**
2953
+ * Scrollbar Width
2954
+ * @see https://tailwindcss.com/docs/scrollbar-width
2955
+ */
2956
+ "scrollbar-w": [{
2957
+ scrollbar: ["auto", "thin", "none"]
2958
+ }],
2959
+ /**
2960
+ * Scroll Margin
2961
+ * @see https://tailwindcss.com/docs/scroll-margin
2962
+ */
2963
+ "scroll-m": [{
2964
+ "scroll-m": scaleUnambiguousSpacing()
2965
+ }],
2966
+ /**
2967
+ * Scroll Margin Inline
2968
+ * @see https://tailwindcss.com/docs/scroll-margin
2969
+ */
2970
+ "scroll-mx": [{
2971
+ "scroll-mx": scaleUnambiguousSpacing()
2972
+ }],
2973
+ /**
2974
+ * Scroll Margin Block
2975
+ * @see https://tailwindcss.com/docs/scroll-margin
2976
+ */
2977
+ "scroll-my": [{
2978
+ "scroll-my": scaleUnambiguousSpacing()
2979
+ }],
2980
+ /**
2981
+ * Scroll Margin Inline Start
2982
+ * @see https://tailwindcss.com/docs/scroll-margin
2983
+ */
2984
+ "scroll-ms": [{
2985
+ "scroll-ms": scaleUnambiguousSpacing()
2986
+ }],
2987
+ /**
2988
+ * Scroll Margin Inline End
2989
+ * @see https://tailwindcss.com/docs/scroll-margin
2990
+ */
2991
+ "scroll-me": [{
2992
+ "scroll-me": scaleUnambiguousSpacing()
2993
+ }],
2994
+ /**
2995
+ * Scroll Margin Block Start
2996
+ * @see https://tailwindcss.com/docs/scroll-margin
2997
+ */
2998
+ "scroll-mbs": [{
2999
+ "scroll-mbs": scaleUnambiguousSpacing()
3000
+ }],
3001
+ /**
3002
+ * Scroll Margin Block End
3003
+ * @see https://tailwindcss.com/docs/scroll-margin
3004
+ */
3005
+ "scroll-mbe": [{
3006
+ "scroll-mbe": scaleUnambiguousSpacing()
3007
+ }],
3008
+ /**
3009
+ * Scroll Margin Top
3010
+ * @see https://tailwindcss.com/docs/scroll-margin
3011
+ */
3012
+ "scroll-mt": [{
3013
+ "scroll-mt": scaleUnambiguousSpacing()
3014
+ }],
3015
+ /**
3016
+ * Scroll Margin Right
3017
+ * @see https://tailwindcss.com/docs/scroll-margin
3018
+ */
3019
+ "scroll-mr": [{
3020
+ "scroll-mr": scaleUnambiguousSpacing()
3021
+ }],
3022
+ /**
3023
+ * Scroll Margin Bottom
3024
+ * @see https://tailwindcss.com/docs/scroll-margin
3025
+ */
3026
+ "scroll-mb": [{
3027
+ "scroll-mb": scaleUnambiguousSpacing()
3028
+ }],
3029
+ /**
3030
+ * Scroll Margin Left
3031
+ * @see https://tailwindcss.com/docs/scroll-margin
3032
+ */
3033
+ "scroll-ml": [{
3034
+ "scroll-ml": scaleUnambiguousSpacing()
3035
+ }],
3036
+ /**
3037
+ * Scroll Padding
3038
+ * @see https://tailwindcss.com/docs/scroll-padding
3039
+ */
3040
+ "scroll-p": [{
3041
+ "scroll-p": scaleUnambiguousSpacing()
3042
+ }],
3043
+ /**
3044
+ * Scroll Padding Inline
3045
+ * @see https://tailwindcss.com/docs/scroll-padding
3046
+ */
3047
+ "scroll-px": [{
3048
+ "scroll-px": scaleUnambiguousSpacing()
3049
+ }],
3050
+ /**
3051
+ * Scroll Padding Block
3052
+ * @see https://tailwindcss.com/docs/scroll-padding
3053
+ */
3054
+ "scroll-py": [{
3055
+ "scroll-py": scaleUnambiguousSpacing()
3056
+ }],
3057
+ /**
3058
+ * Scroll Padding Inline Start
3059
+ * @see https://tailwindcss.com/docs/scroll-padding
3060
+ */
3061
+ "scroll-ps": [{
3062
+ "scroll-ps": scaleUnambiguousSpacing()
3063
+ }],
3064
+ /**
3065
+ * Scroll Padding Inline End
3066
+ * @see https://tailwindcss.com/docs/scroll-padding
3067
+ */
3068
+ "scroll-pe": [{
3069
+ "scroll-pe": scaleUnambiguousSpacing()
3070
+ }],
3071
+ /**
3072
+ * Scroll Padding Block Start
3073
+ * @see https://tailwindcss.com/docs/scroll-padding
3074
+ */
3075
+ "scroll-pbs": [{
3076
+ "scroll-pbs": scaleUnambiguousSpacing()
3077
+ }],
3078
+ /**
3079
+ * Scroll Padding Block End
3080
+ * @see https://tailwindcss.com/docs/scroll-padding
3081
+ */
3082
+ "scroll-pbe": [{
3083
+ "scroll-pbe": scaleUnambiguousSpacing()
3084
+ }],
3085
+ /**
3086
+ * Scroll Padding Top
3087
+ * @see https://tailwindcss.com/docs/scroll-padding
3088
+ */
3089
+ "scroll-pt": [{
3090
+ "scroll-pt": scaleUnambiguousSpacing()
3091
+ }],
3092
+ /**
3093
+ * Scroll Padding Right
3094
+ * @see https://tailwindcss.com/docs/scroll-padding
3095
+ */
3096
+ "scroll-pr": [{
3097
+ "scroll-pr": scaleUnambiguousSpacing()
3098
+ }],
3099
+ /**
3100
+ * Scroll Padding Bottom
3101
+ * @see https://tailwindcss.com/docs/scroll-padding
3102
+ */
3103
+ "scroll-pb": [{
3104
+ "scroll-pb": scaleUnambiguousSpacing()
3105
+ }],
3106
+ /**
3107
+ * Scroll Padding Left
3108
+ * @see https://tailwindcss.com/docs/scroll-padding
3109
+ */
3110
+ "scroll-pl": [{
3111
+ "scroll-pl": scaleUnambiguousSpacing()
3112
+ }],
3113
+ /**
3114
+ * Scroll Snap Align
3115
+ * @see https://tailwindcss.com/docs/scroll-snap-align
3116
+ */
3117
+ "snap-align": [{
3118
+ snap: ["start", "end", "center", "align-none"]
3119
+ }],
3120
+ /**
3121
+ * Scroll Snap Stop
3122
+ * @see https://tailwindcss.com/docs/scroll-snap-stop
3123
+ */
3124
+ "snap-stop": [{
3125
+ snap: ["normal", "always"]
3126
+ }],
3127
+ /**
3128
+ * Scroll Snap Type
3129
+ * @see https://tailwindcss.com/docs/scroll-snap-type
3130
+ */
3131
+ "snap-type": [{
3132
+ snap: ["none", "x", "y", "both"]
3133
+ }],
3134
+ /**
3135
+ * Scroll Snap Type Strictness
3136
+ * @see https://tailwindcss.com/docs/scroll-snap-type
3137
+ */
3138
+ "snap-strictness": [{
3139
+ snap: ["mandatory", "proximity"]
3140
+ }],
3141
+ /**
3142
+ * Touch Action
3143
+ * @see https://tailwindcss.com/docs/touch-action
3144
+ */
3145
+ touch: [{
3146
+ touch: ["auto", "none", "manipulation"]
3147
+ }],
3148
+ /**
3149
+ * Touch Action X
3150
+ * @see https://tailwindcss.com/docs/touch-action
3151
+ */
3152
+ "touch-x": [{
3153
+ "touch-pan": ["x", "left", "right"]
3154
+ }],
3155
+ /**
3156
+ * Touch Action Y
3157
+ * @see https://tailwindcss.com/docs/touch-action
3158
+ */
3159
+ "touch-y": [{
3160
+ "touch-pan": ["y", "up", "down"]
3161
+ }],
3162
+ /**
3163
+ * Touch Action Pinch Zoom
3164
+ * @see https://tailwindcss.com/docs/touch-action
3165
+ */
3166
+ "touch-pz": ["touch-pinch-zoom"],
3167
+ /**
3168
+ * User Select
3169
+ * @see https://tailwindcss.com/docs/user-select
3170
+ */
3171
+ select: [{
3172
+ select: ["none", "text", "all", "auto"]
3173
+ }],
3174
+ /**
3175
+ * Will Change
3176
+ * @see https://tailwindcss.com/docs/will-change
3177
+ */
3178
+ "will-change": [{
3179
+ "will-change": ["auto", "scroll", "contents", "transform", isArbitraryVariable, isArbitraryValue]
3180
+ }],
3181
+ // -----------
3182
+ // --- SVG ---
3183
+ // -----------
3184
+ /**
3185
+ * Fill
3186
+ * @see https://tailwindcss.com/docs/fill
3187
+ */
3188
+ fill: [{
3189
+ fill: ["none", ...scaleColor()]
3190
+ }],
3191
+ /**
3192
+ * Stroke Width
3193
+ * @see https://tailwindcss.com/docs/stroke-width
3194
+ */
3195
+ "stroke-w": [{
3196
+ stroke: [isNumber, isArbitraryVariableLength, isArbitraryLength, isArbitraryNumber]
3197
+ }],
3198
+ /**
3199
+ * Stroke
3200
+ * @see https://tailwindcss.com/docs/stroke
3201
+ */
3202
+ stroke: [{
3203
+ stroke: ["none", ...scaleColor()]
3204
+ }],
3205
+ // ---------------------
3206
+ // --- Accessibility ---
3207
+ // ---------------------
3208
+ /**
3209
+ * Forced Color Adjust
3210
+ * @see https://tailwindcss.com/docs/forced-color-adjust
3211
+ */
3212
+ "forced-color-adjust": [{
3213
+ "forced-color-adjust": ["auto", "none"]
3214
+ }]
3215
+ },
3216
+ conflictingClassGroups: {
3217
+ "container-named": ["container-type"],
3218
+ overflow: ["overflow-x", "overflow-y"],
3219
+ overscroll: ["overscroll-x", "overscroll-y"],
3220
+ inset: ["inset-x", "inset-y", "inset-bs", "inset-be", "start", "end", "top", "right", "bottom", "left"],
3221
+ "inset-x": ["right", "left"],
3222
+ "inset-y": ["top", "bottom"],
3223
+ flex: ["basis", "grow", "shrink"],
3224
+ gap: ["gap-x", "gap-y"],
3225
+ p: ["px", "py", "ps", "pe", "pbs", "pbe", "pt", "pr", "pb", "pl"],
3226
+ px: ["pr", "pl"],
3227
+ py: ["pt", "pb"],
3228
+ m: ["mx", "my", "ms", "me", "mbs", "mbe", "mt", "mr", "mb", "ml"],
3229
+ mx: ["mr", "ml"],
3230
+ my: ["mt", "mb"],
3231
+ size: ["w", "h"],
3232
+ "font-size": ["leading"],
3233
+ "fvn-normal": ["fvn-ordinal", "fvn-slashed-zero", "fvn-figure", "fvn-spacing", "fvn-fraction"],
3234
+ "fvn-ordinal": ["fvn-normal"],
3235
+ "fvn-slashed-zero": ["fvn-normal"],
3236
+ "fvn-figure": ["fvn-normal"],
3237
+ "fvn-spacing": ["fvn-normal"],
3238
+ "fvn-fraction": ["fvn-normal"],
3239
+ "line-clamp": ["display", "overflow"],
3240
+ rounded: ["rounded-s", "rounded-e", "rounded-t", "rounded-r", "rounded-b", "rounded-l", "rounded-ss", "rounded-se", "rounded-ee", "rounded-es", "rounded-tl", "rounded-tr", "rounded-br", "rounded-bl"],
3241
+ "rounded-s": ["rounded-ss", "rounded-es"],
3242
+ "rounded-e": ["rounded-se", "rounded-ee"],
3243
+ "rounded-t": ["rounded-tl", "rounded-tr"],
3244
+ "rounded-r": ["rounded-tr", "rounded-br"],
3245
+ "rounded-b": ["rounded-br", "rounded-bl"],
3246
+ "rounded-l": ["rounded-tl", "rounded-bl"],
3247
+ "border-spacing": ["border-spacing-x", "border-spacing-y"],
3248
+ "border-w": ["border-w-x", "border-w-y", "border-w-s", "border-w-e", "border-w-bs", "border-w-be", "border-w-t", "border-w-r", "border-w-b", "border-w-l"],
3249
+ "border-w-x": ["border-w-r", "border-w-l"],
3250
+ "border-w-y": ["border-w-t", "border-w-b"],
3251
+ "border-color": ["border-color-x", "border-color-y", "border-color-s", "border-color-e", "border-color-bs", "border-color-be", "border-color-t", "border-color-r", "border-color-b", "border-color-l"],
3252
+ "border-color-x": ["border-color-r", "border-color-l"],
3253
+ "border-color-y": ["border-color-t", "border-color-b"],
3254
+ translate: ["translate-x", "translate-y", "translate-none"],
3255
+ "translate-none": ["translate", "translate-x", "translate-y", "translate-z"],
3256
+ "scroll-m": ["scroll-mx", "scroll-my", "scroll-ms", "scroll-me", "scroll-mbs", "scroll-mbe", "scroll-mt", "scroll-mr", "scroll-mb", "scroll-ml"],
3257
+ "scroll-mx": ["scroll-mr", "scroll-ml"],
3258
+ "scroll-my": ["scroll-mt", "scroll-mb"],
3259
+ "scroll-p": ["scroll-px", "scroll-py", "scroll-ps", "scroll-pe", "scroll-pbs", "scroll-pbe", "scroll-pt", "scroll-pr", "scroll-pb", "scroll-pl"],
3260
+ "scroll-px": ["scroll-pr", "scroll-pl"],
3261
+ "scroll-py": ["scroll-pt", "scroll-pb"],
3262
+ touch: ["touch-x", "touch-y", "touch-pz"],
3263
+ "touch-x": ["touch"],
3264
+ "touch-y": ["touch"],
3265
+ "touch-pz": ["touch"]
3266
+ },
3267
+ conflictingClassGroupModifiers: {
3268
+ "font-size": ["leading"]
3269
+ },
3270
+ postfixLookupClassGroups: ["container-type"],
3271
+ orderSensitiveModifiers: ["*", "**", "after", "backdrop", "before", "details-content", "file", "first-letter", "first-line", "marker", "placeholder", "selection"]
3272
+ };
3273
+ };
3274
+ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
3275
+
3276
+ // src/lib/utils.ts
3277
+ function cn(...inputs) {
3278
+ return twMerge(clsx(inputs));
3279
+ }
3280
+
3281
+ // node_modules/class-variance-authority/dist/index.mjs
3282
+ var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
3283
+ var cx = clsx;
3284
+ var cva = (base, config) => (props) => {
3285
+ var _config_compoundVariants;
3286
+ if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3287
+ const { variants, defaultVariants } = config;
3288
+ const getVariantClassNames = Object.keys(variants).map((variant) => {
3289
+ const variantProp = props === null || props === void 0 ? void 0 : props[variant];
3290
+ const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
3291
+ if (variantProp === null) return null;
3292
+ const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
3293
+ return variants[variant][variantKey];
3294
+ });
3295
+ const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
3296
+ let [key, value] = param;
3297
+ if (value === void 0) {
3298
+ return acc;
3299
+ }
3300
+ acc[key] = value;
3301
+ return acc;
3302
+ }, {});
3303
+ const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param) => {
3304
+ let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;
3305
+ return Object.entries(compoundVariantOptions).every((param2) => {
3306
+ let [key, value] = param2;
3307
+ return Array.isArray(value) ? value.includes({
3308
+ ...defaultVariants,
3309
+ ...propsWithoutUndefined
3310
+ }[key]) : {
3311
+ ...defaultVariants,
3312
+ ...propsWithoutUndefined
3313
+ }[key] === value;
3314
+ }) ? [
3315
+ ...acc,
3316
+ cvClass,
3317
+ cvClassName
3318
+ ] : acc;
3319
+ }, []);
3320
+ return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3321
+ };
3322
+
3323
+ // src/ui/toggle.tsx
3324
+ import { Toggle as TogglePrimitive } from "radix-ui";
3325
+ import { jsx } from "react/jsx-runtime";
3326
+ var toggleVariants = cva(
3327
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3328
+ {
3329
+ variants: {
3330
+ variant: {
3331
+ default: "bg-transparent border-0",
3332
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
3333
+ },
3334
+ size: {
3335
+ default: "px-2 py-1",
3336
+ sm: "h-8 min-w-8 px-1.5",
3337
+ lg: "h-10 min-w-10 px-2.5"
3338
+ }
3339
+ },
3340
+ defaultVariants: {
3341
+ variant: "default",
3342
+ size: "default"
3343
+ }
3344
+ }
3345
+ );
3346
+ function Toggle({
3347
+ className,
3348
+ variant,
3349
+ size,
3350
+ ...props
3351
+ }) {
3352
+ return /* @__PURE__ */ jsx(
3353
+ TogglePrimitive.Root,
3354
+ {
3355
+ "data-slot": "toggle",
3356
+ className: cn(toggleVariants({ variant, size, className })),
3357
+ ...props
3358
+ }
3359
+ );
3360
+ }
3361
+
3362
+ // src/ui/toggle-group.tsx
3363
+ import { jsx as jsx2 } from "react/jsx-runtime";
3364
+ var ToggleGroupContext = React.createContext({
3365
+ value: "",
3366
+ onValueChange: () => {
3367
+ }
3368
+ });
3369
+ function ToggleGroup({
3370
+ className,
3371
+ value,
3372
+ onValueChange,
3373
+ children,
3374
+ ...props
3375
+ }) {
3376
+ return /* @__PURE__ */ jsx2(
3377
+ "div",
3378
+ {
3379
+ role: "group",
3380
+ className: cn("flex items-center gap-1 p-1 bg-muted rounded-md", className),
3381
+ ...props,
3382
+ children: /* @__PURE__ */ jsx2(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
3383
+ }
3384
+ );
3385
+ }
3386
+ function ToggleGroupItem({
3387
+ className,
3388
+ value,
3389
+ children,
3390
+ ...props
3391
+ }) {
3392
+ const { value: groupValue, onValueChange } = React.useContext(ToggleGroupContext);
3393
+ return /* @__PURE__ */ jsx2(
3394
+ Toggle,
3395
+ {
3396
+ pressed: groupValue === value,
3397
+ onPressedChange: () => onValueChange(value),
3398
+ className: cn(
3399
+ "text-foreground cursor-pointer hover:bg-transparent hover:text-foreground",
3400
+ "data-[state=on]:bg-background data-[state=on]:shadow-sm",
3401
+ "data-[state=off]:opacity-50 data-[state=off]:hover:opacity-75",
3402
+ className
3403
+ ),
3404
+ ...props,
3405
+ children
3406
+ }
3407
+ );
3408
+ }
3409
+
3410
+ // src/OhhwellsBridge.tsx
3411
+ import { createPortal } from "react-dom";
3412
+ import { usePathname, useRouter, useSearchParams } from "next/navigation";
3413
+
3414
+ // src/lib/session-search.ts
3415
+ var STORAGE_KEY = "ohw-preserved-search";
3416
+ function readPreservedSearch() {
3417
+ if (typeof window === "undefined") return "";
3418
+ const fromUrl = window.location.search;
3419
+ if (fromUrl && fromUrl !== "?") {
3420
+ sessionStorage.setItem(STORAGE_KEY, fromUrl);
3421
+ return fromUrl;
3422
+ }
3423
+ return sessionStorage.getItem(STORAGE_KEY) ?? "";
3424
+ }
3425
+ function isEditSessionActive() {
3426
+ const search = readPreservedSearch();
3427
+ if (!search || search === "?") return false;
3428
+ const q = search.startsWith("?") ? search.slice(1) : search;
3429
+ return new URLSearchParams(q).get("mode") === "edit";
3430
+ }
3431
+
3432
+ // src/OhhwellsBridge.tsx
3433
+ import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
3434
+ var PRIMARY = "#0885FE";
3435
+ var IMAGE_FADE_MS = 300;
3436
+ function runOpacityFade(el, onDone) {
3437
+ const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
3438
+ duration: IMAGE_FADE_MS,
3439
+ easing: "ease",
3440
+ fill: "forwards"
3441
+ });
3442
+ let finished = false;
3443
+ const finish = () => {
3444
+ if (finished) return;
3445
+ finished = true;
3446
+ anim.cancel();
3447
+ el.style.opacity = "";
3448
+ onDone();
3449
+ };
3450
+ anim.finished.then(finish).catch(finish);
3451
+ window.setTimeout(finish, IMAGE_FADE_MS + 100);
3452
+ }
3453
+ function fadeInImageElement(img, onReady) {
3454
+ onReady();
3455
+ img.style.opacity = "0";
3456
+ runOpacityFade(img, () => {
3457
+ img.style.opacity = "";
3458
+ });
3459
+ }
3460
+ function fadeInBgImage(el, url, onReady) {
3461
+ const prevPos = el.style.position;
3462
+ if (!prevPos || prevPos === "static") el.style.position = "relative";
3463
+ const layer = document.createElement("div");
3464
+ layer.setAttribute("data-ohw-bg-fade-layer", "");
3465
+ Object.assign(layer.style, {
3466
+ position: "absolute",
3467
+ inset: "0",
3468
+ zIndex: "0",
3469
+ backgroundImage: `url('${url}')`,
3470
+ backgroundSize: "cover",
3471
+ backgroundPosition: "center",
3472
+ backgroundRepeat: "no-repeat",
3473
+ opacity: "0",
3474
+ pointerEvents: "none"
3475
+ });
3476
+ el.prepend(layer);
3477
+ onReady();
3478
+ runOpacityFade(layer, () => {
3479
+ el.style.backgroundImage = `url('${url}')`;
3480
+ layer.remove();
3481
+ if (!prevPos || prevPos === "static") el.style.position = prevPos;
3482
+ });
3483
+ }
3484
+ function collectEditableNodes() {
3485
+ return Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
3486
+ if (el.dataset.ohwEditable === "image") {
3487
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
3488
+ return { key: el.dataset.ohwKey ?? "", type: "image", text: img?.src ?? "" };
3489
+ }
3490
+ if (el.dataset.ohwEditable === "bg-image") {
3491
+ const raw = el.style.backgroundImage;
3492
+ const url = raw.replace(/^url\(['"]?/, "").replace(/['"]?\)$/, "");
3493
+ return { key: el.dataset.ohwKey ?? "", type: "bg-image", text: url };
3494
+ }
3495
+ return {
3496
+ key: el.dataset.ohwKey ?? "",
3497
+ type: el.dataset.ohwEditable ?? "text",
3498
+ text: el.dataset.ohwEditable === "plain" ? el.innerText ?? "" : el.innerHTML
3499
+ };
3500
+ });
3501
+ }
3502
+ var FORCE_PSEUDO_STATES = [
3503
+ { pseudo: ":hover", state: "hover" },
3504
+ { pseudo: ":focus", state: "focus" },
3505
+ { pseudo: ":focus-visible", state: "focus-visible" },
3506
+ { pseudo: ":active", state: "active" }
3507
+ ];
3508
+ function buildHoverSuppressor(rule) {
3509
+ const props = [];
3510
+ for (let i = 0; i < rule.style.length; i++) props.push(rule.style.item(i));
3511
+ if (props.length === 0) return null;
3512
+ const suppressorSelectors = [];
3513
+ for (const sel of rule.selectorText.split(",").map((s) => s.trim())) {
3514
+ if (!sel.includes(":hover")) continue;
3515
+ const idx = sel.indexOf(":hover");
3516
+ suppressorSelectors.push(
3517
+ sel.slice(0, idx) + '[data-ohw-editable-state]:not([data-ohw-active-state="hover"])' + sel.slice(idx)
3518
+ );
3519
+ }
3520
+ if (suppressorSelectors.length === 0) return null;
3521
+ const firstSel = rule.selectorText.split(",")[0].trim();
3522
+ const hoverIdx = firstSel.indexOf(":hover");
3523
+ const descendantPart = firstSel.slice(hoverIdx + ":hover".length).trim();
3524
+ let targetEl = null;
3525
+ try {
3526
+ targetEl = descendantPart ? document.querySelector(`[data-ohw-editable-state] ${descendantPart}`) : document.querySelector("[data-ohw-editable-state]");
3527
+ } catch {
3528
+ return null;
3529
+ }
3530
+ if (!targetEl) return null;
3531
+ const cs = getComputedStyle(targetEl);
3532
+ const decls = props.map((p) => `${p}: ${cs.getPropertyValue(p)} !important`).join("; ");
3533
+ return `${suppressorSelectors.join(", ")} { ${decls} }`;
3534
+ }
3535
+ function applyStateViews(container, state) {
3536
+ container.querySelectorAll("[data-ohw-state-view]").forEach((view) => {
3537
+ view.style.display = view.getAttribute("data-ohw-state-view") === state ? "block" : "none";
3538
+ });
3539
+ }
3540
+ function resetStateViews() {
3541
+ document.querySelectorAll("[data-ohw-state-view]").forEach((el) => {
3542
+ el.style.display = "";
3543
+ });
3544
+ }
3545
+ function collectStateRules() {
3546
+ const lines = [];
3547
+ function processRules(rules) {
3548
+ for (const rule of Array.from(rules)) {
3549
+ if (rule instanceof CSSStyleRule) {
3550
+ let text = rule.cssText;
3551
+ let matched = false;
3552
+ for (const { pseudo, state } of FORCE_PSEUDO_STATES) {
3553
+ if (text.includes(pseudo)) {
3554
+ text = text.replace(new RegExp(pseudo.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "(?![\\w-])", "g"), `[data-ohw-active-state="${state}"]`);
3555
+ if (pseudo === ":hover") {
3556
+ const suppressor = buildHoverSuppressor(rule);
3557
+ if (suppressor) lines.push(suppressor);
3558
+ }
3559
+ matched = true;
3560
+ }
3561
+ }
3562
+ if (matched) lines.push(text);
3563
+ } else if ("cssRules" in rule) {
3564
+ processRules(rule.cssRules);
3565
+ }
3566
+ }
3567
+ }
3568
+ for (const sheet of Array.from(document.styleSheets)) {
3569
+ try {
3570
+ processRules(sheet.cssRules);
3571
+ } catch {
3572
+ }
3573
+ }
3574
+ return lines.join("\n");
3575
+ }
3576
+ var SAFE_TAGS = /* @__PURE__ */ new Set([
3577
+ "B",
3578
+ "I",
3579
+ "U",
3580
+ "S",
3581
+ "STRIKE",
3582
+ "STRONG",
3583
+ "EM",
3584
+ "BR",
3585
+ "P",
3586
+ "DIV",
3587
+ "SPAN",
3588
+ "OL",
3589
+ "UL",
3590
+ "LI"
3591
+ ]);
3592
+ function sanitizeHtml(html) {
3593
+ const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
3594
+ function walk(parent) {
3595
+ for (const child of Array.from(parent.childNodes)) {
3596
+ if (child.nodeType !== Node.ELEMENT_NODE) continue;
3597
+ const el = child;
3598
+ if (!SAFE_TAGS.has(el.tagName)) {
3599
+ parent.replaceChild(document.createTextNode(el.textContent ?? ""), el);
3600
+ } else {
3601
+ const textAlign = el.style?.textAlign || el.getAttribute("align") || "";
3602
+ for (const attr of Array.from(el.attributes)) el.removeAttribute(attr.name);
3603
+ if (textAlign) el.style.textAlign = textAlign;
3604
+ walk(el);
3605
+ }
3606
+ }
3607
+ }
3608
+ walk(doc.body);
3609
+ return doc.body.innerHTML;
3610
+ }
3611
+ var ICONS = {
3612
+ bold: '<path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/>',
3613
+ italic: '<line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/>',
3614
+ underline: '<path d="M6 4v6a6 6 0 0 0 12 0V4"/><line x1="4" y1="20" x2="20" y2="20"/>',
3615
+ strikeThrough: '<path d="M16 4H9a3 3 0 0 0-2.83 4"/><path d="M14 12a4 4 0 0 1 0 8H6"/><line x1="4" y1="12" x2="20" y2="12"/>',
3616
+ justifyLeft: '<line x1="21" y1="6" x2="3" y2="6"/><line x1="15" y1="12" x2="3" y2="12"/><line x1="17" y1="18" x2="3" y2="18"/>',
3617
+ justifyCenter: '<line x1="21" y1="6" x2="3" y2="6"/><line x1="17" y1="12" x2="7" y2="12"/><line x1="19" y1="18" x2="5" y2="18"/>',
3618
+ justifyRight: '<line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="12" x2="9" y2="12"/><line x1="21" y1="18" x2="7" y2="18"/>',
3619
+ insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
3620
+ insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
3621
+ };
3622
+ var TOOLBAR_GROUPS = [
3623
+ [
3624
+ { cmd: "bold", title: "Bold" },
3625
+ { cmd: "italic", title: "Italic" },
3626
+ { cmd: "underline", title: "Underline" },
3627
+ { cmd: "strikeThrough", title: "Strikethrough" }
3628
+ ],
3629
+ [
3630
+ { cmd: "justifyLeft", title: "Align Left" },
3631
+ { cmd: "justifyCenter", title: "Align Center" },
3632
+ { cmd: "justifyRight", title: "Align Right" }
3633
+ ],
3634
+ [
3635
+ { cmd: "insertUnorderedList", title: "Bullet List" },
3636
+ { cmd: "insertOrderedList", title: "Numbered List" }
3637
+ ]
3638
+ ];
3639
+ function GlowFrame({ rect, elRef }) {
3640
+ const GAP = 6;
3641
+ return /* @__PURE__ */ jsx3(
3642
+ "div",
3643
+ {
3644
+ ref: elRef,
3645
+ style: {
3646
+ position: "fixed",
3647
+ top: rect.top - GAP,
3648
+ left: rect.left - GAP,
3649
+ width: rect.width + GAP * 2,
3650
+ height: rect.height + GAP * 2,
3651
+ border: "2px solid #0885FE",
3652
+ borderRadius: 8,
3653
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
3654
+ pointerEvents: "none",
3655
+ zIndex: 2147483646
3656
+ }
3657
+ }
3658
+ );
3659
+ }
3660
+ function calcToolbarPos(rect, parentScroll) {
3661
+ const GAP = 8;
3662
+ const APPROX_H = 36;
3663
+ const APPROX_W = 330;
3664
+ const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
3665
+ const visibleTop = rect.top - canvasTopInIframe;
3666
+ const visibleBottom = rect.bottom - canvasTopInIframe;
3667
+ const isTall = rect.height > APPROX_H + GAP;
3668
+ let top;
3669
+ let transform;
3670
+ if (visibleTop > 0 || !isTall) {
3671
+ top = rect.top - GAP;
3672
+ transform = "translateX(-50%) translateY(-100%)";
3673
+ } else if (visibleBottom > APPROX_H + GAP) {
3674
+ top = canvasTopInIframe + GAP;
3675
+ transform = "translateX(-50%)";
3676
+ } else {
3677
+ top = rect.bottom + GAP;
3678
+ transform = "translateX(-50%)";
3679
+ }
3680
+ const rawLeft = rect.left + rect.width / 2;
3681
+ const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
3682
+ return { top, left, transform };
3683
+ }
3684
+ function FloatingToolbar({
3685
+ rect,
3686
+ parentScroll,
3687
+ elRef,
3688
+ onCommand,
3689
+ activeCommands
3690
+ }) {
3691
+ const { top, left, transform } = calcToolbarPos(rect, parentScroll);
3692
+ return /* @__PURE__ */ jsx3(
3693
+ "div",
3694
+ {
3695
+ ref: elRef,
3696
+ "data-ohw-toolbar": "",
3697
+ style: {
3698
+ position: "fixed",
3699
+ top,
3700
+ left,
3701
+ transform,
3702
+ zIndex: 2147483647,
3703
+ background: "#fff",
3704
+ border: "1px solid #E7E5E4",
3705
+ borderRadius: 6,
3706
+ boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
3707
+ display: "flex",
3708
+ alignItems: "center",
3709
+ padding: 4,
3710
+ gap: 6,
3711
+ fontFamily: "sans-serif",
3712
+ pointerEvents: "auto",
3713
+ whiteSpace: "nowrap"
3714
+ },
3715
+ children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
3716
+ gi > 0 && /* @__PURE__ */ jsx3("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
3717
+ btns.map((btn) => {
3718
+ const isActive = activeCommands.has(btn.cmd);
3719
+ return /* @__PURE__ */ jsx3(
3720
+ "button",
3721
+ {
3722
+ title: btn.title,
3723
+ onMouseDown: (e) => {
3724
+ e.preventDefault();
3725
+ onCommand(btn.cmd);
3726
+ },
3727
+ onMouseEnter: (e) => {
3728
+ if (!isActive) e.currentTarget.style.background = "#F5F5F4";
3729
+ },
3730
+ onMouseLeave: (e) => {
3731
+ if (!isActive) e.currentTarget.style.background = "transparent";
3732
+ },
3733
+ style: {
3734
+ display: "flex",
3735
+ alignItems: "center",
3736
+ justifyContent: "center",
3737
+ border: "none",
3738
+ background: isActive ? PRIMARY : "transparent",
3739
+ borderRadius: 4,
3740
+ cursor: "pointer",
3741
+ color: isActive ? "#FFFFFF" : "#1C1917",
3742
+ flexShrink: 0,
3743
+ padding: 6
3744
+ },
3745
+ children: /* @__PURE__ */ jsx3(
3746
+ "svg",
3747
+ {
3748
+ width: "16",
3749
+ height: "16",
3750
+ viewBox: "0 0 24 24",
3751
+ fill: "none",
3752
+ stroke: isActive ? "#FFFFFF" : "#1C1917",
3753
+ strokeWidth: "2.5",
3754
+ strokeLinecap: "round",
3755
+ strokeLinejoin: "round",
3756
+ style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px #fff)" } : void 0,
3757
+ dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] }
3758
+ }
3759
+ )
3760
+ },
3761
+ btn.cmd
3762
+ );
3763
+ })
3764
+ ] }, gi))
3765
+ }
3766
+ );
3767
+ }
3768
+ function deriveStates(attr) {
3769
+ if (!attr) return [];
3770
+ return ["Default", ...attr.split(",").map((s) => s.trim().charAt(0).toUpperCase() + s.trim().slice(1))];
3771
+ }
3772
+ function StateToggle({
3773
+ rect,
3774
+ activeState,
3775
+ states,
3776
+ onStateChange
3777
+ }) {
3778
+ return /* @__PURE__ */ jsx3(
3779
+ ToggleGroup,
3780
+ {
3781
+ "data-ohw-state-toggle": "",
3782
+ "data-ohw-bridge": "",
3783
+ value: activeState,
3784
+ onValueChange: onStateChange,
3785
+ onMouseDown: (e) => e.preventDefault(),
3786
+ className: "fixed z-2147483647 pointer-events-auto shadow-popover",
3787
+ style: {
3788
+ top: rect.top + 8,
3789
+ left: rect.right - 8,
3790
+ transform: "translateX(-100%)"
3791
+ },
3792
+ children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, children: state }, state))
3793
+ }
3794
+ );
3795
+ }
3796
+ var contentCache = /* @__PURE__ */ new Map();
3797
+ function OhhwellsBridge() {
3798
+ const pathname = usePathname();
3799
+ const router = useRouter();
3800
+ const searchParams = useSearchParams();
3801
+ const isEditMode = isEditSessionActive();
3802
+ useEffect(() => {
3803
+ if (!isEditMode) return;
3804
+ const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3805
+ const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3806
+ const stylesheet = Object.assign(document.createElement("link"), { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap" });
3807
+ document.head.append(preconnect1, preconnect2, stylesheet);
3808
+ return () => {
3809
+ preconnect1.remove();
3810
+ preconnect2.remove();
3811
+ stylesheet.remove();
3812
+ };
3813
+ }, [isEditMode]);
3814
+ const [bridgeRoot, setBridgeRoot] = useState(null);
3815
+ useEffect(() => {
3816
+ const el = document.createElement("div");
3817
+ el.setAttribute("data-ohw-bridge-root", "");
3818
+ el.setAttribute("data-ohw-bridge", "");
3819
+ el.className = "font-sans";
3820
+ document.body.appendChild(el);
3821
+ setBridgeRoot(el);
3822
+ return () => {
3823
+ el.remove();
3824
+ };
3825
+ }, []);
3826
+ const subdomainFromQuery = searchParams.get("subdomain");
3827
+ const subdomain = subdomainFromQuery ?? (() => {
3828
+ if (typeof window === "undefined") return "";
3829
+ const parts = window.location.hostname.split(".");
3830
+ return parts.length >= 3 && parts[0] !== "www" ? parts[0] : "";
3831
+ })();
3832
+ const postToParent = useCallback((data) => {
3833
+ if (typeof window !== "undefined" && window.parent !== window) {
3834
+ window.parent.postMessage(data, "*");
3835
+ }
3836
+ }, []);
3837
+ const [fetchState, setFetchState] = useState("idle");
3838
+ const autoSaveTimers = useRef(/* @__PURE__ */ new Map());
3839
+ const activeElRef = useRef(null);
3840
+ const originalContentRef = useRef(null);
3841
+ const activeStateElRef = useRef(null);
3842
+ const parentScrollRef = useRef(null);
3843
+ const toolbarElRef = useRef(null);
3844
+ const glowElRef = useRef(null);
3845
+ const hoveredImageRef = useRef(null);
3846
+ const editStylesRef = useRef(null);
3847
+ const activateRef = useRef(() => {
3848
+ });
3849
+ const deactivateRef = useRef(() => {
3850
+ });
3851
+ const refreshActiveCommandsRef = useRef(() => {
3852
+ });
3853
+ const postToParentRef = useRef(postToParent);
3854
+ postToParentRef.current = postToParent;
3855
+ const [toolbarRect, setToolbarRect] = useState(null);
3856
+ const [toggleState, setToggleState] = useState(null);
3857
+ const [maxBadge, setMaxBadge] = useState(null);
3858
+ const [activeCommands, setActiveCommands] = useState(/* @__PURE__ */ new Set());
3859
+ useEffect(() => {
3860
+ const update = () => {
3861
+ const el = activeElRef.current;
3862
+ if (el) setToolbarRect(el.getBoundingClientRect());
3863
+ setToggleState((prev) => {
3864
+ if (!prev || !activeStateElRef.current) return prev;
3865
+ return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
3866
+ });
3867
+ };
3868
+ const vvp = window.visualViewport;
3869
+ if (!vvp) return;
3870
+ vvp.addEventListener("scroll", update);
3871
+ vvp.addEventListener("resize", update);
3872
+ return () => {
3873
+ vvp.removeEventListener("scroll", update);
3874
+ vvp.removeEventListener("resize", update);
3875
+ };
3876
+ }, []);
3877
+ const refreshStateRules = useCallback(() => {
3878
+ editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
3879
+ }, []);
3880
+ const deactivate = useCallback(() => {
3881
+ const el = activeElRef.current;
3882
+ if (!el) return;
3883
+ el.removeAttribute("contenteditable");
3884
+ activeElRef.current = null;
3885
+ setToolbarRect(null);
3886
+ setMaxBadge(null);
3887
+ setActiveCommands(/* @__PURE__ */ new Set());
3888
+ postToParent({ type: "ow:exit-edit" });
3889
+ }, [postToParent]);
3890
+ const activate = useCallback((el) => {
3891
+ if (activeElRef.current === el) return;
3892
+ deactivate();
3893
+ el.setAttribute("contenteditable", "true");
3894
+ el.removeAttribute("data-ohw-hovered");
3895
+ activeElRef.current = el;
3896
+ originalContentRef.current = el.innerHTML;
3897
+ el.focus();
3898
+ setToolbarRect(el.getBoundingClientRect());
3899
+ postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
3900
+ requestAnimationFrame(() => refreshActiveCommandsRef.current());
3901
+ }, [deactivate, postToParent]);
3902
+ activateRef.current = activate;
3903
+ deactivateRef.current = deactivate;
3904
+ useLayoutEffect(() => {
3905
+ if (!subdomain || isEditMode) {
3906
+ setFetchState("done");
3907
+ return;
3908
+ }
3909
+ const applyContent = (content) => {
3910
+ const imageLoads = [];
3911
+ for (const [key, val] of Object.entries(content)) {
3912
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
3913
+ if (el.dataset.ohwEditable === "image") {
3914
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
3915
+ if (img && img.src !== val) {
3916
+ img.src = val;
3917
+ imageLoads.push(new Promise((resolve) => {
3918
+ img.onload = () => resolve();
3919
+ img.onerror = () => resolve();
3920
+ }));
3921
+ }
3922
+ } else if (el.dataset.ohwEditable === "bg-image") {
3923
+ const next = `url('${val}')`;
3924
+ if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
3925
+ } else if (el.innerHTML !== val) {
3926
+ el.innerHTML = val;
3927
+ }
3928
+ });
3929
+ }
3930
+ return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
3931
+ }) : Promise.resolve();
3932
+ };
3933
+ const cached = contentCache.get(subdomain);
3934
+ if (cached) {
3935
+ applyContent(cached).finally(() => setFetchState("done"));
3936
+ return;
3937
+ }
3938
+ let cancelled = false;
3939
+ setFetchState("loading");
3940
+ const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "http://localhost:4005";
3941
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
3942
+ if (cancelled) return;
3943
+ const content = data?.content ?? {};
3944
+ contentCache.set(subdomain, content);
3945
+ return applyContent(content);
3946
+ }).catch(() => {
3947
+ }).finally(() => {
3948
+ if (!cancelled) setFetchState("done");
3949
+ });
3950
+ return () => {
3951
+ cancelled = true;
3952
+ };
3953
+ }, [subdomain, isEditMode, pathname]);
3954
+ useEffect(() => {
3955
+ if (!subdomain || isEditMode) return;
3956
+ const applyFromCache = () => {
3957
+ const content = contentCache.get(subdomain);
3958
+ if (!content) return;
3959
+ for (const [key, val] of Object.entries(content)) {
3960
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
3961
+ if (el.dataset.ohwEditable === "image") {
3962
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
3963
+ if (img && img.src !== val) img.src = val;
3964
+ } else if (el.dataset.ohwEditable === "bg-image") {
3965
+ const next = `url('${val}')`;
3966
+ if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
3967
+ } else if (el.innerHTML !== val) {
3968
+ el.innerHTML = val;
3969
+ }
3970
+ });
3971
+ }
3972
+ };
3973
+ applyFromCache();
3974
+ const observer = new MutationObserver(applyFromCache);
3975
+ observer.observe(document.body, { childList: true, subtree: true });
3976
+ return () => observer.disconnect();
3977
+ }, [subdomain, isEditMode]);
3978
+ useLayoutEffect(() => {
3979
+ const el = document.getElementById("ohw-loader");
3980
+ if (!el) return;
3981
+ const visible = Boolean(subdomain) && fetchState !== "done";
3982
+ el.style.display = visible ? "flex" : "none";
3983
+ }, [subdomain, fetchState]);
3984
+ useEffect(() => {
3985
+ postToParent({ type: "ow:navigation", path: pathname });
3986
+ }, [pathname, postToParent]);
3987
+ useEffect(() => {
3988
+ if (!isEditMode) return;
3989
+ const measure = () => {
3990
+ const h = document.body.scrollHeight;
3991
+ if (h > 50) postToParent({ type: "ow:height", height: h });
3992
+ };
3993
+ const t1 = setTimeout(measure, 50);
3994
+ const t2 = setTimeout(measure, 500);
3995
+ let lastWidth = window.innerWidth;
3996
+ let resizeTimer = null;
3997
+ const handleResize = () => {
3998
+ if (window.innerWidth === lastWidth) return;
3999
+ lastWidth = window.innerWidth;
4000
+ if (resizeTimer) clearTimeout(resizeTimer);
4001
+ resizeTimer = setTimeout(measure, 150);
4002
+ };
4003
+ window.addEventListener("resize", handleResize);
4004
+ return () => {
4005
+ clearTimeout(t1);
4006
+ clearTimeout(t2);
4007
+ if (resizeTimer) clearTimeout(resizeTimer);
4008
+ window.removeEventListener("resize", handleResize);
4009
+ };
4010
+ }, [pathname, isEditMode, postToParent]);
4011
+ useEffect(() => {
4012
+ if (!subdomainFromQuery || isEditMode) return;
4013
+ const handleClick = (e) => {
4014
+ const anchor = e.target.closest("a");
4015
+ if (!anchor || anchor.target === "_blank" || e.defaultPrevented) return;
4016
+ const href = anchor.getAttribute("href");
4017
+ if (!href || /^(https?:|mailto:|tel:|#)/.test(href)) return;
4018
+ const url = new URL(href, window.location.origin);
4019
+ if (url.searchParams.has("subdomain")) return;
4020
+ e.preventDefault();
4021
+ url.searchParams.set("subdomain", subdomainFromQuery);
4022
+ router.push(url.pathname + url.search);
4023
+ };
4024
+ document.addEventListener("click", handleClick, true);
4025
+ return () => document.removeEventListener("click", handleClick, true);
4026
+ }, [subdomainFromQuery, isEditMode, router]);
4027
+ useEffect(() => {
4028
+ if (!isEditMode) {
4029
+ editStylesRef.current?.base.remove();
4030
+ editStylesRef.current?.forceHover.remove();
4031
+ editStylesRef.current?.stateViews.remove();
4032
+ editStylesRef.current = null;
4033
+ return;
4034
+ }
4035
+ if (!editStylesRef.current) {
4036
+ const initialVh = window.innerHeight;
4037
+ const base = document.createElement("style");
4038
+ base.setAttribute("data-ohw-edit-style", "");
4039
+ base.textContent = `
4040
+ html { height: auto !important; }
4041
+ body { height: auto !important; min-height: 0 !important; overflow: hidden !important; }
4042
+ .min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${initialVh}px !important; }
4043
+ .h-screen, .h-svh, .h-dvh { height: ${initialVh}px !important; }
4044
+ [style*="100vh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
4045
+ [style*="100svh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
4046
+ [style*="100dvh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
4047
+ [data-ohw-editable] {
4048
+ display: block;
4049
+ }
4050
+ [data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]) { cursor: text !important; }
4051
+ [data-ohw-editable="image"], [data-ohw-editable="image"] *,
4052
+ [data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
4053
+ [data-ohw-hovered]:not([contenteditable]) {
4054
+ outline: 2px dashed ${PRIMARY} !important;
4055
+ outline-offset: 4px;
4056
+ border-radius: 2px;
4057
+ }
4058
+ [data-ohw-editable][contenteditable] {
4059
+ outline: none !important;
4060
+ caret-color: ${PRIMARY};
4061
+ cursor: text !important;
4062
+ }
4063
+ [data-ohw-editable][contenteditable]::selection,
4064
+ [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
4065
+ [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
4066
+ [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
4067
+ `;
4068
+ const forceHover = document.createElement("style");
4069
+ forceHover.setAttribute("data-ohw-active-state-style", "");
4070
+ const stateViews = document.createElement("style");
4071
+ stateViews.setAttribute("data-ohw-state-views-style", "");
4072
+ stateViews.textContent = `
4073
+ [data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
4074
+ [data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
4075
+ [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY} !important; outline-offset: 4px; border-radius: 2px; }
4076
+ [data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
4077
+ `;
4078
+ document.head.appendChild(base);
4079
+ document.head.appendChild(forceHover);
4080
+ document.head.appendChild(stateViews);
4081
+ editStylesRef.current = { base, forceHover, stateViews };
4082
+ }
4083
+ refreshStateRules();
4084
+ const handleClick = (e) => {
4085
+ const target = e.target;
4086
+ if (target.closest("[data-ohw-toolbar]")) return;
4087
+ if (target.closest("[data-ohw-state-toggle]")) return;
4088
+ if (target.closest("[data-ohw-max-badge]")) return;
4089
+ const editable = target.closest("[data-ohw-editable]");
4090
+ if (editable) {
4091
+ if (editable.dataset.ohwEditable === "image" || editable.dataset.ohwEditable === "bg-image") {
4092
+ e.preventDefault();
4093
+ postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "" });
4094
+ return;
4095
+ }
4096
+ e.preventDefault();
4097
+ activateRef.current(editable);
4098
+ return;
4099
+ }
4100
+ if (activeElRef.current) {
4101
+ const sel = window.getSelection();
4102
+ if (sel && !sel.isCollapsed) {
4103
+ const range = sel.getRangeAt(0);
4104
+ if (activeElRef.current.contains(range.commonAncestorContainer)) return;
4105
+ }
4106
+ }
4107
+ const anchor = target.closest("a");
4108
+ if (anchor) e.preventDefault();
4109
+ deactivateRef.current();
4110
+ };
4111
+ const handleMouseOver = (e) => {
4112
+ const editable = e.target.closest("[data-ohw-editable]");
4113
+ if (!editable) return;
4114
+ if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
4115
+ editable.setAttribute("data-ohw-hovered", "");
4116
+ }
4117
+ };
4118
+ const handleMouseOut = (e) => {
4119
+ const editable = e.target.closest("[data-ohw-editable]");
4120
+ if (!editable) return;
4121
+ if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
4122
+ editable.removeAttribute("data-ohw-hovered");
4123
+ }
4124
+ };
4125
+ const toProbeCoords = (clientX, clientY, fromParentViewport) => {
4126
+ if (!fromParentViewport) return { x: clientX, y: clientY };
4127
+ const frame = window.frameElement;
4128
+ if (!frame) return { x: clientX, y: clientY };
4129
+ const fr = frame.getBoundingClientRect();
4130
+ return {
4131
+ x: clientX - fr.left - frame.clientLeft,
4132
+ y: clientY - fr.top - frame.clientTop
4133
+ };
4134
+ };
4135
+ const uploadLockedTracks = /* @__PURE__ */ new Set();
4136
+ const resumeAnimTracks = () => {
4137
+ document.querySelectorAll("[data-ohw-hover-paused]").forEach((el) => {
4138
+ if (!uploadLockedTracks.has(el)) el.removeAttribute("data-ohw-hover-paused");
4139
+ });
4140
+ };
4141
+ const getVisibleRect = (el) => {
4142
+ const r2 = el.getBoundingClientRect();
4143
+ let top = r2.top, left = r2.left, bottom = r2.bottom, right = r2.right;
4144
+ let parent = el.parentElement;
4145
+ while (parent) {
4146
+ const style = getComputedStyle(parent);
4147
+ if (style.overflowY === "hidden" || style.overflowY === "clip" || style.overflowX === "hidden" || style.overflowX === "clip") {
4148
+ const pr = parent.getBoundingClientRect();
4149
+ top = Math.max(top, pr.top);
4150
+ bottom = Math.min(bottom, pr.bottom);
4151
+ left = Math.max(left, pr.left);
4152
+ right = Math.min(right, pr.right);
4153
+ }
4154
+ if (parent === document.documentElement) break;
4155
+ parent = parent.parentElement;
4156
+ }
4157
+ return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
4158
+ };
4159
+ const postImageHover = (imgEl, isDragOver = false) => {
4160
+ const r2 = getVisibleRect(imgEl);
4161
+ postToParentRef.current({
4162
+ type: "ow:image-hover",
4163
+ key: imgEl.dataset.ohwKey ?? "",
4164
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
4165
+ ...isDragOver ? { isDragOver: true } : {}
4166
+ });
4167
+ const track = imgEl.closest("[data-ohw-hover-pause]");
4168
+ if (track) track.setAttribute("data-ohw-hover-paused", "");
4169
+ };
4170
+ const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
4171
+ const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4172
+ const images = Array.from(document.querySelectorAll('[data-ohw-editable="image"], [data-ohw-editable="bg-image"]'));
4173
+ const matches = [];
4174
+ for (let i = images.length - 1; i >= 0; i--) {
4175
+ const el = images[i];
4176
+ const ownerCard = el.closest("[data-ohw-editable-state]");
4177
+ if (ownerCard) {
4178
+ const inHoverState = ownerCard.getAttribute("data-ohw-active-state") === "hover";
4179
+ const elState = el.dataset.ohwState;
4180
+ if (el === ownerCard && inHoverState) continue;
4181
+ if (elState === "default" && inHoverState) continue;
4182
+ if (elState === "hover" && !inHoverState) continue;
4183
+ }
4184
+ const r2 = getVisibleRect(el);
4185
+ if (x >= r2.left && x <= r2.left + r2.width && y >= r2.top && y <= r2.top + r2.height) matches.push(el);
4186
+ }
4187
+ if (matches.length === 0) return null;
4188
+ const imageTypeMatches = matches.filter((el) => el.dataset.ohwEditable === "image");
4189
+ const candidatePool = imageTypeMatches.length > 0 ? imageTypeMatches : matches;
4190
+ const smallest = candidatePool.reduce((best, el) => {
4191
+ const br = getVisibleRect(best);
4192
+ const er = getVisibleRect(el);
4193
+ return er.width * er.height < br.width * br.height ? el : best;
4194
+ });
4195
+ const pinned = hoveredImageRef.current;
4196
+ if (pinned && candidatePool.includes(pinned)) {
4197
+ const pr = getVisibleRect(pinned);
4198
+ const stickyPad = 48;
4199
+ const withinPad = x >= pr.left - stickyPad && x <= pr.left + pr.width + stickyPad && y >= pr.top - stickyPad && y <= pr.top + pr.height + stickyPad;
4200
+ if (withinPad) {
4201
+ const yieldToSmaller = smallest !== pinned && candidatePool.includes(smallest) && (() => {
4202
+ const sr = getVisibleRect(smallest);
4203
+ const pr2 = getVisibleRect(pinned);
4204
+ return sr.width * sr.height < pr2.width * pr2.height;
4205
+ })();
4206
+ if (!yieldToSmaller) return pinned;
4207
+ }
4208
+ }
4209
+ return smallest;
4210
+ };
4211
+ const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false, fromOverlay = false) => {
4212
+ const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4213
+ if (toggleEl) {
4214
+ const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4215
+ const tr = toggleEl.getBoundingClientRect();
4216
+ if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
4217
+ if (hoveredImageRef.current) {
4218
+ hoveredImageRef.current = null;
4219
+ resumeAnimTracks();
4220
+ postToParentRef.current({ type: "ow:image-unhover" });
4221
+ }
4222
+ return;
4223
+ }
4224
+ }
4225
+ const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
4226
+ if (imgEl) {
4227
+ const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4228
+ const topEl = document.elementFromPoint(x, y);
4229
+ if (topEl?.closest("[data-ohw-toolbar]")) {
4230
+ if (hoveredImageRef.current) {
4231
+ hoveredImageRef.current = null;
4232
+ resumeAnimTracks();
4233
+ postToParentRef.current({ type: "ow:image-unhover" });
4234
+ }
4235
+ return;
4236
+ }
4237
+ const topEditable = topEl?.closest("[data-ohw-editable]");
4238
+ if (topEditable && topEditable.dataset.ohwEditable !== "image" && topEditable.dataset.ohwEditable !== "bg-image") {
4239
+ if (topEditable.hasAttribute("contenteditable") && fromOverlay) return;
4240
+ if (hoveredImageRef.current) {
4241
+ hoveredImageRef.current = null;
4242
+ resumeAnimTracks();
4243
+ postToParentRef.current({ type: "ow:image-unhover" });
4244
+ }
4245
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4246
+ topEditable.setAttribute("data-ohw-hovered", "");
4247
+ return;
4248
+ }
4249
+ const activeHovered = document.querySelector("[data-ohw-hovered]");
4250
+ if (activeHovered) {
4251
+ const outlinePad = 8;
4252
+ const hr = activeHovered.getBoundingClientRect();
4253
+ if (x >= hr.left - outlinePad && x <= hr.right + outlinePad && y >= hr.top - outlinePad && y <= hr.bottom + outlinePad) {
4254
+ if (hoveredImageRef.current) {
4255
+ hoveredImageRef.current = null;
4256
+ resumeAnimTracks();
4257
+ postToParentRef.current({ type: "ow:image-unhover" });
4258
+ }
4259
+ return;
4260
+ }
4261
+ }
4262
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4263
+ if (imgEl !== hoveredImageRef.current) {
4264
+ hoveredImageRef.current = imgEl;
4265
+ postImageHover(imgEl, isDragOver);
4266
+ } else if (isDragOver) {
4267
+ postImageHover(imgEl, true);
4268
+ }
4269
+ } else {
4270
+ const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
4271
+ if (!inIframeView) return;
4272
+ hoveredImageRef.current = null;
4273
+ resumeAnimTracks();
4274
+ postToParentRef.current({ type: "ow:image-unhover" });
4275
+ }
4276
+ };
4277
+ const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
4278
+ const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4279
+ const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4280
+ if (toggleEl) {
4281
+ const tr = toggleEl.getBoundingClientRect();
4282
+ if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
4283
+ return;
4284
+ }
4285
+ }
4286
+ const cards = Array.from(document.querySelectorAll("[data-ohw-editable-state]"));
4287
+ const found = cards.find((card) => {
4288
+ const r2 = card.getBoundingClientRect();
4289
+ return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
4290
+ }) ?? null;
4291
+ const currentLocked = activeStateElRef.current?.hasAttribute("data-ohw-active-state") ? activeStateElRef.current : null;
4292
+ const active = found ?? currentLocked;
4293
+ activeStateElRef.current = active;
4294
+ document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4295
+ if (active) {
4296
+ if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4297
+ const states = deriveStates(active.dataset.ohwEditableState ?? "");
4298
+ const activeState = active.hasAttribute("data-ohw-active-state") ? (active.getAttribute("data-ohw-active-state") ?? "Default").charAt(0).toUpperCase() + (active.getAttribute("data-ohw-active-state") ?? "").slice(1) : "Default";
4299
+ setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4300
+ } else {
4301
+ setToggleState(null);
4302
+ }
4303
+ };
4304
+ const handleMouseMove = (e) => {
4305
+ const { clientX, clientY } = e;
4306
+ probeImageAt(clientX, clientY);
4307
+ probeHoverCardsAt(clientX, clientY);
4308
+ };
4309
+ const handlePointerSync = (e) => {
4310
+ if (e.data?.type !== "ow:pointer-sync") return;
4311
+ const { clientX, clientY, fromOverlay } = e.data;
4312
+ if (typeof clientX !== "number" || typeof clientY !== "number") return;
4313
+ probeImageAt(clientX, clientY, false, false, fromOverlay ?? false);
4314
+ probeHoverCardsAt(clientX, clientY);
4315
+ };
4316
+ const handleDragOver = (e) => {
4317
+ e.preventDefault();
4318
+ const el = findImageAtPoint(e.clientX, e.clientY, false);
4319
+ if (!el) {
4320
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "none";
4321
+ return;
4322
+ }
4323
+ e.dataTransfer.dropEffect = "copy";
4324
+ if (hoveredImageRef.current !== el) {
4325
+ hoveredImageRef.current = el;
4326
+ postImageHover(el, true);
4327
+ }
4328
+ };
4329
+ const handleDragLeave = (e) => {
4330
+ const imgEl = findImageAtPoint(e.clientX, e.clientY, false);
4331
+ if (imgEl) return;
4332
+ hoveredImageRef.current = null;
4333
+ resumeAnimTracks();
4334
+ postToParentRef.current({ type: "ow:image-unhover" });
4335
+ };
4336
+ const handleDrop = (e) => {
4337
+ e.preventDefault();
4338
+ const el = findImageAtPoint(e.clientX, e.clientY, false);
4339
+ if (!el) return;
4340
+ const file = e.dataTransfer?.files?.[0];
4341
+ if (file) {
4342
+ if (file.type.startsWith("image/")) {
4343
+ const key = el.dataset.ohwKey ?? "";
4344
+ const { name, type: mimeType } = file;
4345
+ const r2 = el.getBoundingClientRect();
4346
+ const rect = { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
4347
+ file.arrayBuffer().then((buf) => {
4348
+ window.parent.postMessage({ type: "ow:image-drop", key, name, mimeType, buf, rect }, "*", [buf]);
4349
+ });
4350
+ } else {
4351
+ postToParentRef.current({ type: "ow:image-drop-invalid" });
4352
+ }
4353
+ }
4354
+ hoveredImageRef.current = null;
4355
+ resumeAnimTracks();
4356
+ postToParentRef.current({ type: "ow:image-unhover" });
4357
+ };
4358
+ const handleImageUrl = (e) => {
4359
+ if (e.data?.type !== "ow:image-url") return;
4360
+ const { key, url } = e.data;
4361
+ let notified = false;
4362
+ const notify = () => {
4363
+ if (notified) return;
4364
+ notified = true;
4365
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
4366
+ const track = el.closest("[data-ohw-hover-pause]");
4367
+ if (track) {
4368
+ uploadLockedTracks.delete(track);
4369
+ const stillHovered = hoveredImageRef.current && track.contains(hoveredImageRef.current);
4370
+ if (!stillHovered) track.removeAttribute("data-ohw-hover-paused");
4371
+ }
4372
+ });
4373
+ hoveredImageRef.current = null;
4374
+ postToParentRef.current({ type: "ow:image-loaded", key });
4375
+ };
4376
+ let found = false;
4377
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
4378
+ const track = el.closest("[data-ohw-hover-pause]");
4379
+ if (track) {
4380
+ track.setAttribute("data-ohw-hover-paused", "");
4381
+ }
4382
+ if (el.dataset.ohwEditable === "bg-image") {
4383
+ found = true;
4384
+ const fadeTarget = el;
4385
+ const preload = new Image();
4386
+ preload.onload = () => fadeInBgImage(fadeTarget, url, notify);
4387
+ preload.onerror = () => {
4388
+ fadeTarget.style.backgroundImage = `url('${url}')`;
4389
+ notify();
4390
+ };
4391
+ preload.src = url;
4392
+ } else if (el.dataset.ohwEditable === "image") {
4393
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
4394
+ if (img) {
4395
+ found = true;
4396
+ img.style.opacity = "0";
4397
+ const onReady = () => {
4398
+ img.onload = null;
4399
+ img.onerror = null;
4400
+ fadeInImageElement(img, notify);
4401
+ };
4402
+ img.onload = onReady;
4403
+ img.onerror = onReady;
4404
+ img.src = url;
4405
+ if (img.complete && img.naturalWidth > 0) {
4406
+ requestAnimationFrame(() => onReady());
4407
+ }
4408
+ }
4409
+ }
4410
+ });
4411
+ if (!found) notify();
4412
+ };
4413
+ const handlePaste = (e) => {
4414
+ const el = e.target.closest("[data-ohw-editable]");
4415
+ if (!el) return;
4416
+ e.preventDefault();
4417
+ const text = e.clipboardData?.getData("text/plain") ?? "";
4418
+ const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
4419
+ if (maxLen) {
4420
+ const current = el.innerText.replace(/\n$/, "").length;
4421
+ const remaining = Math.max(0, maxLen - current);
4422
+ document.execCommand("insertText", false, text.slice(0, remaining));
4423
+ } else {
4424
+ document.execCommand("insertText", false, text);
4425
+ }
4426
+ };
4427
+ const handleInput = (e) => {
4428
+ const el = e.target;
4429
+ const key = el.dataset.ohwKey;
4430
+ if (!key) return;
4431
+ if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
4432
+ const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
4433
+ if (maxLen) {
4434
+ const current = el.innerText.replace(/\n$/, "").length;
4435
+ if (current > maxLen) {
4436
+ const sel = window.getSelection();
4437
+ const range = sel?.getRangeAt(0);
4438
+ const offset = range?.startOffset ?? 0;
4439
+ el.innerText = el.innerText.replace(/\n$/, "").slice(0, maxLen);
4440
+ const textNode = el.firstChild;
4441
+ if (textNode && sel && range) {
4442
+ const newRange = document.createRange();
4443
+ newRange.setStart(textNode, Math.min(offset - (current - maxLen), maxLen));
4444
+ newRange.collapse(true);
4445
+ sel.removeAllRanges();
4446
+ sel.addRange(newRange);
4447
+ }
4448
+ }
4449
+ setMaxBadge({ rect: el.getBoundingClientRect(), current: Math.min(current, maxLen), max: maxLen });
4450
+ }
4451
+ const html = sanitizeHtml(el.innerHTML);
4452
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((sibling) => {
4453
+ if (sibling !== el) sibling.innerHTML = html;
4454
+ });
4455
+ const timers = autoSaveTimers.current;
4456
+ const existing = timers.get(key);
4457
+ if (existing) clearTimeout(existing);
4458
+ timers.set(key, setTimeout(() => {
4459
+ timers.delete(key);
4460
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
4461
+ const h = document.documentElement.scrollHeight;
4462
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
4463
+ }, 400));
4464
+ };
4465
+ const handleHydrate = (e) => {
4466
+ if (e.data?.type !== "ow:hydrate") return;
4467
+ const content = e.data.content;
4468
+ if (!content) return;
4469
+ for (const [key, val] of Object.entries(content)) {
4470
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
4471
+ if (el.dataset.ohwEditable === "image") {
4472
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
4473
+ if (img) img.src = val;
4474
+ } else if (el.dataset.ohwEditable === "bg-image") {
4475
+ el.style.backgroundImage = `url('${val}')`;
4476
+ } else {
4477
+ el.innerHTML = val;
4478
+ }
4479
+ });
4480
+ }
4481
+ postToParentRef.current({ type: "ow:hydrate-done" });
4482
+ };
4483
+ window.addEventListener("message", handleHydrate);
4484
+ const handleDeactivate = (e) => {
4485
+ if (e.data?.type !== "ow:deactivate") return;
4486
+ deactivateRef.current();
4487
+ };
4488
+ window.addEventListener("message", handleDeactivate);
4489
+ const handleKeyDown = (e) => {
4490
+ if (e.key !== "Escape") return;
4491
+ const el = activeElRef.current;
4492
+ if (el && originalContentRef.current !== null) {
4493
+ el.innerHTML = originalContentRef.current;
4494
+ const key = el.dataset.ohwKey;
4495
+ if (key) {
4496
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text: originalContentRef.current }] });
4497
+ }
4498
+ }
4499
+ deactivateRef.current();
4500
+ };
4501
+ const handleScroll = () => {
4502
+ if (activeElRef.current) {
4503
+ const r2 = activeElRef.current.getBoundingClientRect();
4504
+ applyToolbarPos(r2);
4505
+ setMaxBadge((prev) => prev ? { ...prev, rect: r2 } : null);
4506
+ }
4507
+ if (activeStateElRef.current) {
4508
+ const rect = activeStateElRef.current.getBoundingClientRect();
4509
+ setToggleState((prev) => prev ? { ...prev, rect } : null);
4510
+ }
4511
+ if (hoveredImageRef.current) {
4512
+ const r2 = hoveredImageRef.current.getBoundingClientRect();
4513
+ postToParentRef.current({
4514
+ type: "ow:image-hover",
4515
+ key: hoveredImageRef.current.dataset.ohwKey ?? "",
4516
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
4517
+ });
4518
+ }
4519
+ };
4520
+ const handleSave = (e) => {
4521
+ if (e.data?.type !== "ow:save") return;
4522
+ postToParentRef.current({ type: "ow:save-result", nodes: collectEditableNodes() });
4523
+ };
4524
+ const handleSelectionChange = () => {
4525
+ if (!activeElRef.current) return;
4526
+ const next = /* @__PURE__ */ new Set();
4527
+ for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
4528
+ try {
4529
+ if (document.queryCommandState(cmd)) next.add(cmd);
4530
+ } catch {
4531
+ }
4532
+ }
4533
+ const sel = window.getSelection();
4534
+ const anchor = sel?.anchorNode;
4535
+ if (anchor) {
4536
+ const el = anchor.nodeType === Node.TEXT_NODE ? anchor.parentElement : anchor;
4537
+ const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
4538
+ if (block) {
4539
+ const align = getComputedStyle(block).textAlign;
4540
+ if (align === "center") next.add("justifyCenter");
4541
+ else if (align === "right" || align === "end") next.add("justifyRight");
4542
+ else next.add("justifyLeft");
4543
+ }
4544
+ }
4545
+ setActiveCommands(next);
4546
+ };
4547
+ refreshActiveCommandsRef.current = handleSelectionChange;
4548
+ const handleDocMouseLeave = () => {
4549
+ hoveredImageRef.current = null;
4550
+ document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4551
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4552
+ activeStateElRef.current = null;
4553
+ setToggleState(null);
4554
+ };
4555
+ const handleAnimLock = (e) => {
4556
+ if (e.data?.type !== "ow:anim-lock") return;
4557
+ const { key } = e.data;
4558
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
4559
+ const track = el.closest("[data-ohw-hover-pause]");
4560
+ if (track) {
4561
+ uploadLockedTracks.add(track);
4562
+ track.setAttribute("data-ohw-hover-paused", "");
4563
+ }
4564
+ });
4565
+ };
4566
+ const handleCanvasHeight = (e) => {
4567
+ if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
4568
+ document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
4569
+ };
4570
+ const applyToolbarPos = (rect) => {
4571
+ const ps = parentScrollRef.current;
4572
+ if (toolbarElRef.current) {
4573
+ const { top, left, transform } = calcToolbarPos(rect, ps);
4574
+ toolbarElRef.current.style.top = `${top}px`;
4575
+ toolbarElRef.current.style.left = `${left}px`;
4576
+ toolbarElRef.current.style.transform = transform;
4577
+ }
4578
+ if (glowElRef.current) {
4579
+ const GAP = 6;
4580
+ glowElRef.current.style.top = `${rect.top - GAP}px`;
4581
+ glowElRef.current.style.left = `${rect.left - GAP}px`;
4582
+ }
4583
+ };
4584
+ const handleParentScroll = (e) => {
4585
+ if (e.data?.type !== "ow:parent-scroll") return;
4586
+ const { iframeOffsetTop, headerH, canvasH } = e.data;
4587
+ parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
4588
+ if (activeElRef.current) applyToolbarPos(activeElRef.current.getBoundingClientRect());
4589
+ };
4590
+ window.addEventListener("message", handleSave);
4591
+ window.addEventListener("message", handleImageUrl);
4592
+ window.addEventListener("message", handleAnimLock);
4593
+ window.addEventListener("message", handleCanvasHeight);
4594
+ window.addEventListener("message", handleParentScroll);
4595
+ window.addEventListener("message", handlePointerSync);
4596
+ document.addEventListener("click", handleClick, true);
4597
+ document.addEventListener("paste", handlePaste, true);
4598
+ document.addEventListener("input", handleInput, true);
4599
+ document.addEventListener("mouseover", handleMouseOver, true);
4600
+ document.addEventListener("mouseout", handleMouseOut, true);
4601
+ document.addEventListener("mousemove", handleMouseMove, true);
4602
+ document.addEventListener("mouseleave", handleDocMouseLeave);
4603
+ document.addEventListener("dragover", handleDragOver, true);
4604
+ document.addEventListener("dragleave", handleDragLeave, true);
4605
+ document.addEventListener("drop", handleDrop, true);
4606
+ document.addEventListener("keydown", handleKeyDown);
4607
+ document.addEventListener("selectionchange", handleSelectionChange);
4608
+ window.addEventListener("scroll", handleScroll, true);
4609
+ return () => {
4610
+ document.removeEventListener("click", handleClick, true);
4611
+ document.removeEventListener("paste", handlePaste, true);
4612
+ document.removeEventListener("input", handleInput, true);
4613
+ document.removeEventListener("mouseover", handleMouseOver, true);
4614
+ document.removeEventListener("mouseout", handleMouseOut, true);
4615
+ document.removeEventListener("mousemove", handleMouseMove, true);
4616
+ document.removeEventListener("mouseleave", handleDocMouseLeave);
4617
+ document.removeEventListener("dragover", handleDragOver, true);
4618
+ document.removeEventListener("dragleave", handleDragLeave, true);
4619
+ document.removeEventListener("drop", handleDrop, true);
4620
+ document.removeEventListener("keydown", handleKeyDown);
4621
+ document.removeEventListener("selectionchange", handleSelectionChange);
4622
+ window.removeEventListener("scroll", handleScroll, true);
4623
+ window.removeEventListener("message", handleSave);
4624
+ window.removeEventListener("message", handleImageUrl);
4625
+ window.removeEventListener("message", handleAnimLock);
4626
+ window.removeEventListener("message", handleCanvasHeight);
4627
+ window.removeEventListener("message", handleParentScroll);
4628
+ window.removeEventListener("message", handlePointerSync);
4629
+ window.removeEventListener("message", handleHydrate);
4630
+ window.removeEventListener("message", handleDeactivate);
4631
+ autoSaveTimers.current.forEach(clearTimeout);
4632
+ autoSaveTimers.current.clear();
4633
+ };
4634
+ }, [isEditMode, refreshStateRules]);
4635
+ useEffect(() => {
4636
+ if (!isEditMode) return;
4637
+ document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
4638
+ el.removeAttribute("data-ohw-active-state");
4639
+ });
4640
+ resetStateViews();
4641
+ document.querySelectorAll("[data-ohw-editable-state]").forEach((el) => {
4642
+ if (el.querySelector("[data-ohw-state-view]")) applyStateViews(el, "default");
4643
+ });
4644
+ activeStateElRef.current = null;
4645
+ setToggleState(null);
4646
+ refreshStateRules();
4647
+ const raf = requestAnimationFrame(() => refreshStateRules());
4648
+ const timer = setTimeout(() => {
4649
+ refreshStateRules();
4650
+ postToParent({ type: "ow:ready", version: "1", nodes: collectEditableNodes() });
4651
+ }, 150);
4652
+ return () => {
4653
+ cancelAnimationFrame(raf);
4654
+ clearTimeout(timer);
4655
+ };
4656
+ }, [pathname, isEditMode, refreshStateRules, postToParent]);
4657
+ const handleCommand = useCallback((cmd) => {
4658
+ document.execCommand(cmd, false);
4659
+ activeElRef.current?.focus();
4660
+ if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
4661
+ refreshActiveCommandsRef.current();
4662
+ }, []);
4663
+ const handleStateChange = useCallback((state) => {
4664
+ if (!activeStateElRef.current) return;
4665
+ const el = activeStateElRef.current;
4666
+ if (state === "Default") {
4667
+ deactivate();
4668
+ el.removeAttribute("data-ohw-active-state");
4669
+ applyStateViews(el, "default");
4670
+ } else {
4671
+ el.setAttribute("data-ohw-active-state", state.toLowerCase());
4672
+ applyStateViews(el, state.toLowerCase());
4673
+ }
4674
+ setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
4675
+ }, [deactivate]);
4676
+ return bridgeRoot ? createPortal(
4677
+ /* @__PURE__ */ jsxs(Fragment, { children: [
4678
+ toolbarRect && /* @__PURE__ */ jsxs(Fragment, { children: [
4679
+ /* @__PURE__ */ jsx3(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
4680
+ /* @__PURE__ */ jsx3(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
4681
+ ] }),
4682
+ maxBadge && /* @__PURE__ */ jsxs(
4683
+ "div",
4684
+ {
4685
+ "data-ohw-max-badge": "",
4686
+ style: {
4687
+ position: "fixed",
4688
+ top: maxBadge.rect.bottom + 4,
4689
+ left: maxBadge.rect.right,
4690
+ transform: "translateX(-100%)",
4691
+ zIndex: 2147483647,
4692
+ background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
4693
+ color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
4694
+ border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
4695
+ borderRadius: 4,
4696
+ padding: "2px 6px",
4697
+ fontSize: 11,
4698
+ fontWeight: 500,
4699
+ pointerEvents: "none"
4700
+ },
4701
+ children: [
4702
+ maxBadge.current,
4703
+ "/",
4704
+ maxBadge.max
4705
+ ]
4706
+ }
4707
+ ),
4708
+ toggleState && /* @__PURE__ */ jsx3(
4709
+ StateToggle,
4710
+ {
4711
+ rect: toggleState.rect,
4712
+ activeState: toggleState.activeState,
4713
+ states: toggleState.states,
4714
+ onStateChange: handleStateChange
4715
+ }
4716
+ )
4717
+ ] }),
4718
+ bridgeRoot
4719
+ ) : null;
4720
+ }
4721
+ export {
4722
+ OhhwellsBridge,
4723
+ Toggle,
4724
+ ToggleGroup,
4725
+ ToggleGroupItem,
4726
+ toggleVariants
4727
+ };
19
4728
  //# sourceMappingURL=index.js.map