@tenphi/tasty 0.0.0-snapshot.74db5d1 → 0.0.0-snapshot.7a4d0bf
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/styles/border.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CSS_WIDE_KEYWORDS } from "../parser/const.js";
|
|
2
2
|
import { DIRECTIONS, filterMods, parseStyle } from "../utils/styles.js";
|
|
3
3
|
import { BORDER_STYLES } from "./const.js";
|
|
4
|
+
import { extractCSSWideKeyword } from "./shared.js";
|
|
4
5
|
//#region src/styles/border.ts
|
|
5
6
|
/**
|
|
6
7
|
* Process a single group and return border values for its directions.
|
|
@@ -45,14 +46,24 @@ function borderStyle({ border }) {
|
|
|
45
46
|
if (CSS_WIDE_KEYWORDS.has(strBorder)) return { border: strBorder };
|
|
46
47
|
const groups = parseStyle(strBorder).groups ?? [];
|
|
47
48
|
if (!groups.length) return null;
|
|
49
|
+
const useLonghand = groups.some((g) => (g.mods ?? []).includes("longhand"));
|
|
48
50
|
if (groups.length === 1) {
|
|
51
|
+
const group = groups[0];
|
|
52
|
+
const keyword = extractCSSWideKeyword(group);
|
|
53
|
+
if (keyword) {
|
|
54
|
+
if (useLonghand) return Object.fromEntries(DIRECTIONS.map((dir) => [`border-${dir}`, keyword]));
|
|
55
|
+
return { border: keyword };
|
|
56
|
+
}
|
|
49
57
|
const { directions, borderValue } = processGroup({
|
|
50
|
-
values:
|
|
51
|
-
mods:
|
|
52
|
-
colors:
|
|
58
|
+
values: group.values ?? [],
|
|
59
|
+
mods: group.mods ?? [],
|
|
60
|
+
colors: group.colors ?? []
|
|
53
61
|
});
|
|
54
62
|
const styleValue = formatBorderValue(borderValue);
|
|
55
|
-
if (!directions.length)
|
|
63
|
+
if (!directions.length) {
|
|
64
|
+
if (useLonghand) return Object.fromEntries(DIRECTIONS.map((dir) => [`border-${dir}`, styleValue]));
|
|
65
|
+
return { border: styleValue };
|
|
66
|
+
}
|
|
56
67
|
const zeroValue = `0 ${borderValue.style} ${borderValue.color}`;
|
|
57
68
|
return DIRECTIONS.reduce((styles, dir) => {
|
|
58
69
|
if (directions.includes(dir)) styles[`border-${dir}`] = styleValue;
|
|
@@ -82,7 +93,11 @@ function borderStyle({ border }) {
|
|
|
82
93
|
for (const dir of directions) directionMap[dir] = borderValue;
|
|
83
94
|
}
|
|
84
95
|
}
|
|
85
|
-
if (!hasAnyDirections && allDirectionsValue)
|
|
96
|
+
if (!hasAnyDirections && allDirectionsValue) {
|
|
97
|
+
const formatted = formatBorderValue(allDirectionsValue);
|
|
98
|
+
if (useLonghand) return Object.fromEntries(DIRECTIONS.map((dir) => [`border-${dir}`, formatted]));
|
|
99
|
+
return { border: formatted };
|
|
100
|
+
}
|
|
86
101
|
const result = {};
|
|
87
102
|
for (const dir of DIRECTIONS) {
|
|
88
103
|
const value = directionMap[dir];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"border.js","names":[],"sources":["../../src/styles/border.ts"],"sourcesContent":["import { CSS_WIDE_KEYWORDS } from '../parser/const';\nimport { DIRECTIONS, filterMods, parseStyle } from '../utils/styles';\nimport { BORDER_STYLES } from './const';\n\ntype Direction = (typeof DIRECTIONS)[number];\n\ninterface GroupData {\n values: string[];\n mods: string[];\n colors: string[];\n}\n\ninterface BorderValue {\n width: string;\n style: string;\n color: string;\n}\n\n/**\n * Process a single group and return border values for its directions.\n * @returns Object with directions as keys and border values, or null for \"all directions\"\n */\nfunction processGroup(group: GroupData): {\n directions: Direction[];\n borderValue: BorderValue;\n} {\n const { values, mods, colors } = group;\n\n const directions = filterMods(mods, DIRECTIONS) as Direction[];\n const typeMods = filterMods(mods, BORDER_STYLES as unknown as string[]);\n\n const width = values[0] || 'var(--border-width)';\n const style = typeMods[0] || 'solid';\n const color = colors?.[0] || 'var(--border-color, currentColor)';\n\n return {\n directions,\n borderValue: { width, style, color },\n };\n}\n\n/**\n * Format a border value to CSS string.\n */\nfunction formatBorderValue(value: BorderValue): string {\n return `${value.width} ${value.style} ${value.color}`;\n}\n\n/**\n * Border style handler with multi-group support.\n *\n * Single group (backward compatible):\n * - `border=\"1bw solid #red\"` - all sides\n * - `border=\"1bw solid #red top left\"` - only top and left\n *\n * Multi-group (new):\n * - `border=\"1bw #red, 2bw #blue top\"` - all sides red 1bw, then top overridden to blue 2bw\n * - `border=\"1bw, dashed top bottom, #purple left right\"` - base 1bw, dashed on top/bottom, purple on left/right\n *\n * Later groups override earlier groups for conflicting directions.\n */\nexport function borderStyle({\n border,\n}: {\n border?: string | number | boolean;\n}) {\n if (!border && border !== 0) return null;\n\n if (border === true) border = '1bw';\n\n const strBorder = String(border);\n\n if (CSS_WIDE_KEYWORDS.has(strBorder)) {\n return { border: strBorder };\n }\n\n const processed = parseStyle(strBorder);\n const groups
|
|
1
|
+
{"version":3,"file":"border.js","names":[],"sources":["../../src/styles/border.ts"],"sourcesContent":["import { CSS_WIDE_KEYWORDS } from '../parser/const';\nimport { DIRECTIONS, filterMods, parseStyle } from '../utils/styles';\nimport { BORDER_STYLES } from './const';\nimport { extractCSSWideKeyword } from './shared';\n\ntype Direction = (typeof DIRECTIONS)[number];\n\ninterface GroupData {\n values: string[];\n mods: string[];\n colors: string[];\n}\n\ninterface BorderValue {\n width: string;\n style: string;\n color: string;\n}\n\n/**\n * Process a single group and return border values for its directions.\n * @returns Object with directions as keys and border values, or null for \"all directions\"\n */\nfunction processGroup(group: GroupData): {\n directions: Direction[];\n borderValue: BorderValue;\n} {\n const { values, mods, colors } = group;\n\n const directions = filterMods(mods, DIRECTIONS) as Direction[];\n const typeMods = filterMods(mods, BORDER_STYLES as unknown as string[]);\n\n const width = values[0] || 'var(--border-width)';\n const style = typeMods[0] || 'solid';\n const color = colors?.[0] || 'var(--border-color, currentColor)';\n\n return {\n directions,\n borderValue: { width, style, color },\n };\n}\n\n/**\n * Format a border value to CSS string.\n */\nfunction formatBorderValue(value: BorderValue): string {\n return `${value.width} ${value.style} ${value.color}`;\n}\n\n/**\n * Border style handler with multi-group support.\n *\n * Single group (backward compatible):\n * - `border=\"1bw solid #red\"` - all sides\n * - `border=\"1bw solid #red top left\"` - only top and left\n *\n * Multi-group (new):\n * - `border=\"1bw #red, 2bw #blue top\"` - all sides red 1bw, then top overridden to blue 2bw\n * - `border=\"1bw, dashed top bottom, #purple left right\"` - base 1bw, dashed on top/bottom, purple on left/right\n *\n * Later groups override earlier groups for conflicting directions.\n */\nexport function borderStyle({\n border,\n}: {\n border?: string | number | boolean;\n}) {\n if (!border && border !== 0) return null;\n\n if (border === true) border = '1bw';\n\n const strBorder = String(border);\n\n if (CSS_WIDE_KEYWORDS.has(strBorder)) {\n return { border: strBorder };\n }\n\n const processed = parseStyle(strBorder);\n const groups = processed.groups ?? [];\n\n if (!groups.length) return null;\n\n const useLonghand = groups.some((g) => (g.mods ?? []).includes('longhand'));\n\n // Single group - use original logic for backward compatibility\n if (groups.length === 1) {\n const group = groups[0];\n const keyword = extractCSSWideKeyword(group);\n\n if (keyword) {\n if (useLonghand) {\n return Object.fromEntries(\n DIRECTIONS.map((dir) => [`border-${dir}`, keyword]),\n );\n }\n\n return { border: keyword };\n }\n\n const { directions, borderValue } = processGroup({\n values: group.values ?? [],\n mods: group.mods ?? [],\n colors: group.colors ?? [],\n });\n\n const styleValue = formatBorderValue(borderValue);\n\n if (!directions.length) {\n if (useLonghand) {\n return Object.fromEntries(\n DIRECTIONS.map((dir) => [`border-${dir}`, styleValue]),\n );\n }\n\n return { border: styleValue };\n }\n\n const zeroValue = `0 ${borderValue.style} ${borderValue.color}`;\n\n return DIRECTIONS.reduce(\n (styles, dir) => {\n if (directions.includes(dir)) {\n styles[`border-${dir}`] = styleValue;\n } else {\n styles[`border-${dir}`] = zeroValue;\n }\n return styles;\n },\n {} as Record<string, string>,\n );\n }\n\n // Multi-group - process groups in order, later groups override earlier\n // Track whether any group specifies directions\n let hasAnyDirections = false;\n\n // Build a map of direction -> border value\n // Start with undefined (no border set)\n const directionMap: Record<Direction, BorderValue | null> = {\n top: null,\n right: null,\n bottom: null,\n left: null,\n };\n\n // Track the last \"all directions\" value for fallback\n let allDirectionsValue: BorderValue | null = null;\n\n // Process groups in order (first to last)\n for (const group of groups) {\n const { directions, borderValue } = processGroup({\n values: group.values ?? [],\n mods: group.mods ?? [],\n colors: group.colors ?? [],\n });\n\n if (directions.length === 0) {\n // No specific directions - applies to all\n allDirectionsValue = borderValue;\n // Set all directions\n for (const dir of DIRECTIONS) {\n directionMap[dir] = borderValue;\n }\n } else {\n // Specific directions - override only those\n hasAnyDirections = true;\n for (const dir of directions) {\n directionMap[dir] = borderValue;\n }\n }\n }\n\n // If no group specified any directions and we have an all-directions value,\n // return the simple `border` shorthand (or longhands if requested)\n if (!hasAnyDirections && allDirectionsValue) {\n const formatted = formatBorderValue(allDirectionsValue);\n\n if (useLonghand) {\n return Object.fromEntries(\n DIRECTIONS.map((dir) => [`border-${dir}`, formatted]),\n );\n }\n\n return { border: formatted };\n }\n\n // Otherwise, output individual border-* properties\n const result: Record<string, string> = {};\n\n for (const dir of DIRECTIONS) {\n const value = directionMap[dir];\n if (value) {\n result[`border-${dir}`] = formatBorderValue(value);\n } else {\n // No border for this direction - set to 0\n // Use the last all-directions value for style/color consistency, or defaults\n const fallback = allDirectionsValue || {\n width: '0',\n style: 'solid',\n color: 'var(--border-color, currentColor)',\n };\n result[`border-${dir}`] = `0 ${fallback.style} ${fallback.color}`;\n }\n }\n\n return result;\n}\n\nborderStyle.__lookupStyles = ['border'];\n"],"mappings":"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"}
|
|
@@ -71,6 +71,7 @@ function processDirectionalStyle(config, props) {
|
|
|
71
71
|
bottom: defaultInit,
|
|
72
72
|
left: defaultInit
|
|
73
73
|
};
|
|
74
|
+
let useLonghand = false;
|
|
74
75
|
if (main != null) if (typeof main === "number") dirs.top = dirs.right = dirs.bottom = dirs.left = `${main}px`;
|
|
75
76
|
else {
|
|
76
77
|
const strMain = main === true ? trueValue : String(main);
|
|
@@ -80,6 +81,7 @@ function processDirectionalStyle(config, props) {
|
|
|
80
81
|
else {
|
|
81
82
|
const groups = parseStyle(strMain).groups ?? [];
|
|
82
83
|
for (const group of groups) {
|
|
84
|
+
if (group.mods.includes("longhand")) useLonghand = true;
|
|
83
85
|
const kw = extractCSSWideKeyword(group);
|
|
84
86
|
if (kw) {
|
|
85
87
|
const groupDirs = filterMods(group.mods, DIRECTIONS);
|
|
@@ -117,6 +119,12 @@ function processDirectionalStyle(config, props) {
|
|
|
117
119
|
const val = parseSingleValue(left, defaultValue, trueValue);
|
|
118
120
|
if (val) dirs.left = val;
|
|
119
121
|
}
|
|
122
|
+
if (useLonghand) return {
|
|
123
|
+
[dirProp("top")]: dirs.top,
|
|
124
|
+
[dirProp("right")]: dirs.right,
|
|
125
|
+
[dirProp("bottom")]: dirs.bottom,
|
|
126
|
+
[dirProp("left")]: dirs.left
|
|
127
|
+
};
|
|
120
128
|
return optimizeShorthand(property, dirs);
|
|
121
129
|
}
|
|
122
130
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directional.js","names":[],"sources":["../../src/styles/directional.ts"],"sourcesContent":["import type { StyleDetails } from '../parser/types';\nimport { CSS_WIDE_KEYWORDS } from '../parser/const';\nimport { DIRECTIONS, filterMods, parseStyle } from '../utils/styles';\nimport { extractCSSWideKeyword } from './shared';\n\ntype Direction = (typeof DIRECTIONS)[number];\n\nexport interface DirectionalConfig {\n /** CSS property name (e.g. 'padding', 'margin', 'inset', 'scroll-margin') */\n property: string;\n /** Default value when parsing yields empty (e.g. 'var(--gap)', '0') */\n defaultValue: string;\n /** Value used when the prop is `true` (e.g. '1x', '0') */\n trueValue: string;\n /** Default per-direction init value (e.g. '0', 'auto') */\n defaultInit: string;\n /**\n * When true, if only individual direction props are set (no shorthand,\n * no block/inline), output individual CSS properties instead of the\n * shorthand. Needed by inset for correct CSS cascade with modifiers.\n */\n individualOnly?: boolean;\n /**\n * Maps individual direction CSS property names. Defaults to\n * `${property}-top`, `${property}-right`, etc. For inset this is\n * `top`, `right`, `bottom`, `left`.\n */\n directionProperty?: (dir: Direction) => string;\n}\n\nexport function parseSingleValue(\n val: string | number | boolean,\n defaultValue: string,\n trueValue: string,\n): string | null {\n if (typeof val === 'number') return `${val}px`;\n if (!val) return null;\n if (val === true) val = trueValue;\n\n const strVal = String(val);\n\n if (CSS_WIDE_KEYWORDS.has(strVal)) return strVal;\n\n const { values } = parseStyle(strVal).groups[0] ?? { values: [] };\n\n return values[0] || defaultValue;\n}\n\nfunction extractGroupData(\n group: StyleDetails,\n defaultValue: string,\n): {\n values: string[];\n directions: Direction[];\n} {\n const { values = [], mods = [] } = group;\n\n return {\n values: values.length ? values : [defaultValue],\n directions: filterMods(mods, DIRECTIONS) as Direction[],\n };\n}\n\nfunction applyGroup(\n dirs: Record<Direction, string>,\n values: string[],\n directions: Direction[],\n): void {\n if (!values.length) return;\n\n if (directions.length === 0) {\n dirs.top = values[0];\n dirs.right = values[1] || values[0];\n dirs.bottom = values[2] || values[0];\n dirs.left = values[3] || values[1] || values[0];\n } else {\n directions.forEach((dir, i) => {\n dirs[dir] = values[i] ?? values[0];\n });\n }\n}\n\nfunction optimizeShorthand(\n property: string,\n dirs: Record<Direction, string>,\n): Record<string, string> {\n const { top, right, bottom, left } = dirs;\n\n if (top === right && right === bottom && bottom === left) {\n return { [property]: top };\n }\n if (top === bottom && left === right) {\n return { [property]: `${top} ${left}` };\n }\n\n return { [property]: `${top} ${right} ${bottom} ${left}` };\n}\n\nexport interface DirectionalProps {\n main?: string | number | boolean;\n block?: string | number | boolean;\n inline?: string | number | boolean;\n top?: string | number | boolean;\n right?: string | number | boolean;\n bottom?: string | number | boolean;\n left?: string | number | boolean;\n}\n\n/**\n * Core directional style logic shared by padding, margin, inset, scrollMargin.\n */\nexport function processDirectionalStyle(\n config: DirectionalConfig,\n props: DirectionalProps,\n): Record<string, string> | null {\n const { main, block, inline, top, right, bottom, left } = props;\n\n if (\n main == null &&\n block == null &&\n inline == null &&\n top == null &&\n right == null &&\n bottom == null &&\n left == null\n ) {\n return null;\n }\n\n const {\n property,\n defaultValue,\n trueValue,\n defaultInit,\n individualOnly,\n directionProperty,\n } = config;\n const dirProp =\n directionProperty ?? ((dir: Direction) => `${property}-${dir}`);\n\n if (individualOnly) {\n const onlyIndividualProps = main == null && block == null && inline == null;\n\n if (onlyIndividualProps) {\n const result: Record<string, string> = {};\n\n if (top != null) {\n const val = parseSingleValue(top, defaultValue, trueValue);\n if (val) result[dirProp('top')] = val;\n }\n if (right != null) {\n const val = parseSingleValue(right, defaultValue, trueValue);\n if (val) result[dirProp('right')] = val;\n }\n if (bottom != null) {\n const val = parseSingleValue(bottom, defaultValue, trueValue);\n if (val) result[dirProp('bottom')] = val;\n }\n if (left != null) {\n const val = parseSingleValue(left, defaultValue, trueValue);\n if (val) result[dirProp('left')] = val;\n }\n\n return Object.keys(result).length > 0 ? result : null;\n }\n }\n\n const dirs: Record<Direction, string> = {\n top: defaultInit,\n right: defaultInit,\n bottom: defaultInit,\n left: defaultInit,\n };\n\n if (main != null) {\n if (typeof main === 'number') {\n const v = `${main}px`;\n dirs.top = dirs.right = dirs.bottom = dirs.left = v;\n } else {\n const strMain = main === true ? trueValue : String(main);\n\n if (strMain) {\n const keyword = CSS_WIDE_KEYWORDS.has(strMain) ? strMain : null;\n\n if (keyword) {\n dirs.top = dirs.right = dirs.bottom = dirs.left = keyword;\n } else {\n const processed = parseStyle(strMain);\n const groups = processed.groups ?? [];\n\n for (const group of groups) {\n const kw = extractCSSWideKeyword(group);\n\n if (kw) {\n const groupDirs = filterMods(\n group.mods,\n DIRECTIONS,\n ) as Direction[];\n\n if (groupDirs.length === 0) {\n dirs.top = dirs.right = dirs.bottom = dirs.left = kw;\n } else {\n for (const dir of groupDirs) {\n dirs[dir] = kw;\n }\n }\n } else {\n const { values, directions } = extractGroupData(\n group,\n defaultValue,\n );\n applyGroup(dirs, values, directions);\n }\n }\n }\n }\n }\n }\n\n if (block != null) {\n const val = parseSingleValue(block, defaultValue, trueValue);\n if (val) dirs.top = dirs.bottom = val;\n }\n if (inline != null) {\n const val = parseSingleValue(inline, defaultValue, trueValue);\n if (val) dirs.left = dirs.right = val;\n }\n\n if (top != null) {\n const val = parseSingleValue(top, defaultValue, trueValue);\n if (val) dirs.top = val;\n }\n if (right != null) {\n const val = parseSingleValue(right, defaultValue, trueValue);\n if (val) dirs.right = val;\n }\n if (bottom != null) {\n const val = parseSingleValue(bottom, defaultValue, trueValue);\n if (val) dirs.bottom = val;\n }\n if (left != null) {\n const val = parseSingleValue(left, defaultValue, trueValue);\n if (val) dirs.left = val;\n }\n\n return optimizeShorthand(property, dirs);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"directional.js","names":[],"sources":["../../src/styles/directional.ts"],"sourcesContent":["import type { StyleDetails } from '../parser/types';\nimport { CSS_WIDE_KEYWORDS } from '../parser/const';\nimport { DIRECTIONS, filterMods, parseStyle } from '../utils/styles';\nimport { extractCSSWideKeyword } from './shared';\n\ntype Direction = (typeof DIRECTIONS)[number];\n\nexport interface DirectionalConfig {\n /** CSS property name (e.g. 'padding', 'margin', 'inset', 'scroll-margin') */\n property: string;\n /** Default value when parsing yields empty (e.g. 'var(--gap)', '0') */\n defaultValue: string;\n /** Value used when the prop is `true` (e.g. '1x', '0') */\n trueValue: string;\n /** Default per-direction init value (e.g. '0', 'auto') */\n defaultInit: string;\n /**\n * When true, if only individual direction props are set (no shorthand,\n * no block/inline), output individual CSS properties instead of the\n * shorthand. Needed by inset for correct CSS cascade with modifiers.\n */\n individualOnly?: boolean;\n /**\n * Maps individual direction CSS property names. Defaults to\n * `${property}-top`, `${property}-right`, etc. For inset this is\n * `top`, `right`, `bottom`, `left`.\n */\n directionProperty?: (dir: Direction) => string;\n}\n\nexport function parseSingleValue(\n val: string | number | boolean,\n defaultValue: string,\n trueValue: string,\n): string | null {\n if (typeof val === 'number') return `${val}px`;\n if (!val) return null;\n if (val === true) val = trueValue;\n\n const strVal = String(val);\n\n if (CSS_WIDE_KEYWORDS.has(strVal)) return strVal;\n\n const { values } = parseStyle(strVal).groups[0] ?? { values: [] };\n\n return values[0] || defaultValue;\n}\n\nfunction extractGroupData(\n group: StyleDetails,\n defaultValue: string,\n): {\n values: string[];\n directions: Direction[];\n} {\n const { values = [], mods = [] } = group;\n\n return {\n values: values.length ? values : [defaultValue],\n directions: filterMods(mods, DIRECTIONS) as Direction[],\n };\n}\n\nfunction applyGroup(\n dirs: Record<Direction, string>,\n values: string[],\n directions: Direction[],\n): void {\n if (!values.length) return;\n\n if (directions.length === 0) {\n dirs.top = values[0];\n dirs.right = values[1] || values[0];\n dirs.bottom = values[2] || values[0];\n dirs.left = values[3] || values[1] || values[0];\n } else {\n directions.forEach((dir, i) => {\n dirs[dir] = values[i] ?? values[0];\n });\n }\n}\n\nfunction optimizeShorthand(\n property: string,\n dirs: Record<Direction, string>,\n): Record<string, string> {\n const { top, right, bottom, left } = dirs;\n\n if (top === right && right === bottom && bottom === left) {\n return { [property]: top };\n }\n if (top === bottom && left === right) {\n return { [property]: `${top} ${left}` };\n }\n\n return { [property]: `${top} ${right} ${bottom} ${left}` };\n}\n\nexport interface DirectionalProps {\n main?: string | number | boolean;\n block?: string | number | boolean;\n inline?: string | number | boolean;\n top?: string | number | boolean;\n right?: string | number | boolean;\n bottom?: string | number | boolean;\n left?: string | number | boolean;\n}\n\n/**\n * Core directional style logic shared by padding, margin, inset, scrollMargin.\n */\nexport function processDirectionalStyle(\n config: DirectionalConfig,\n props: DirectionalProps,\n): Record<string, string> | null {\n const { main, block, inline, top, right, bottom, left } = props;\n\n if (\n main == null &&\n block == null &&\n inline == null &&\n top == null &&\n right == null &&\n bottom == null &&\n left == null\n ) {\n return null;\n }\n\n const {\n property,\n defaultValue,\n trueValue,\n defaultInit,\n individualOnly,\n directionProperty,\n } = config;\n const dirProp =\n directionProperty ?? ((dir: Direction) => `${property}-${dir}`);\n\n if (individualOnly) {\n const onlyIndividualProps = main == null && block == null && inline == null;\n\n if (onlyIndividualProps) {\n const result: Record<string, string> = {};\n\n if (top != null) {\n const val = parseSingleValue(top, defaultValue, trueValue);\n if (val) result[dirProp('top')] = val;\n }\n if (right != null) {\n const val = parseSingleValue(right, defaultValue, trueValue);\n if (val) result[dirProp('right')] = val;\n }\n if (bottom != null) {\n const val = parseSingleValue(bottom, defaultValue, trueValue);\n if (val) result[dirProp('bottom')] = val;\n }\n if (left != null) {\n const val = parseSingleValue(left, defaultValue, trueValue);\n if (val) result[dirProp('left')] = val;\n }\n\n return Object.keys(result).length > 0 ? result : null;\n }\n }\n\n const dirs: Record<Direction, string> = {\n top: defaultInit,\n right: defaultInit,\n bottom: defaultInit,\n left: defaultInit,\n };\n\n let useLonghand = false;\n\n if (main != null) {\n if (typeof main === 'number') {\n const v = `${main}px`;\n dirs.top = dirs.right = dirs.bottom = dirs.left = v;\n } else {\n const strMain = main === true ? trueValue : String(main);\n\n if (strMain) {\n const keyword = CSS_WIDE_KEYWORDS.has(strMain) ? strMain : null;\n\n if (keyword) {\n dirs.top = dirs.right = dirs.bottom = dirs.left = keyword;\n } else {\n const processed = parseStyle(strMain);\n const groups = processed.groups ?? [];\n\n for (const group of groups) {\n if (group.mods.includes('longhand')) {\n useLonghand = true;\n }\n\n const kw = extractCSSWideKeyword(group);\n\n if (kw) {\n const groupDirs = filterMods(\n group.mods,\n DIRECTIONS,\n ) as Direction[];\n\n if (groupDirs.length === 0) {\n dirs.top = dirs.right = dirs.bottom = dirs.left = kw;\n } else {\n for (const dir of groupDirs) {\n dirs[dir] = kw;\n }\n }\n } else {\n const { values, directions } = extractGroupData(\n group,\n defaultValue,\n );\n applyGroup(dirs, values, directions);\n }\n }\n }\n }\n }\n }\n\n if (block != null) {\n const val = parseSingleValue(block, defaultValue, trueValue);\n if (val) dirs.top = dirs.bottom = val;\n }\n if (inline != null) {\n const val = parseSingleValue(inline, defaultValue, trueValue);\n if (val) dirs.left = dirs.right = val;\n }\n\n if (top != null) {\n const val = parseSingleValue(top, defaultValue, trueValue);\n if (val) dirs.top = val;\n }\n if (right != null) {\n const val = parseSingleValue(right, defaultValue, trueValue);\n if (val) dirs.right = val;\n }\n if (bottom != null) {\n const val = parseSingleValue(bottom, defaultValue, trueValue);\n if (val) dirs.bottom = val;\n }\n if (left != null) {\n const val = parseSingleValue(left, defaultValue, trueValue);\n if (val) dirs.left = val;\n }\n\n if (useLonghand) {\n return {\n [dirProp('top')]: dirs.top,\n [dirProp('right')]: dirs.right,\n [dirProp('bottom')]: dirs.bottom,\n [dirProp('left')]: dirs.left,\n };\n }\n\n return optimizeShorthand(property, dirs);\n}\n"],"mappings":"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"}
|
package/dist/styles/radius.js
CHANGED
|
@@ -18,9 +18,13 @@ function radiusStyle({ radius }) {
|
|
|
18
18
|
const { mods } = group;
|
|
19
19
|
let { values } = group;
|
|
20
20
|
const keyword = extractCSSWideKeyword(group);
|
|
21
|
+
const useLonghand = mods.includes("longhand");
|
|
21
22
|
if (keyword) {
|
|
22
23
|
const dirMods = mods.filter((m) => DIRECTIONS.includes(m));
|
|
23
|
-
if (!dirMods.length)
|
|
24
|
+
if (!dirMods.length) {
|
|
25
|
+
if (useLonghand) return Object.fromEntries(RADIUS_LONGHANDS.map((prop) => [prop, keyword]));
|
|
26
|
+
return { "border-radius": keyword };
|
|
27
|
+
}
|
|
24
28
|
const result = {};
|
|
25
29
|
const corners = /* @__PURE__ */ new Set();
|
|
26
30
|
dirMods.forEach((dir) => {
|
|
@@ -64,6 +68,12 @@ function radiusStyle({ radius }) {
|
|
|
64
68
|
});
|
|
65
69
|
if (flag) values = arr;
|
|
66
70
|
}
|
|
71
|
+
if (useLonghand) return {
|
|
72
|
+
[RADIUS_LONGHANDS[0]]: values[0],
|
|
73
|
+
[RADIUS_LONGHANDS[1]]: values[1] || values[0],
|
|
74
|
+
[RADIUS_LONGHANDS[2]]: values[2] || values[0],
|
|
75
|
+
[RADIUS_LONGHANDS[3]]: values[3] || values[1] || values[0]
|
|
76
|
+
};
|
|
67
77
|
return { "border-radius": values.join(" ") };
|
|
68
78
|
}
|
|
69
79
|
radiusStyle.__lookupStyles = ["radius"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radius.js","names":[],"sources":["../../src/styles/radius.ts"],"sourcesContent":["import { makeEmptyDetails } from '../parser/types';\nimport { DIRECTIONS, parseStyle } from '../utils/styles';\nimport { extractCSSWideKeyword } from './shared';\n\nconst PROP = 'var(--radius)';\nconst SHARP = 'var(--sharp-radius)';\n\nconst RADIUS_LONGHANDS = [\n 'border-top-left-radius',\n 'border-top-right-radius',\n 'border-bottom-right-radius',\n 'border-bottom-left-radius',\n];\n\nexport function radiusStyle({\n radius,\n}: {\n radius?: string | number | boolean;\n}) {\n if (typeof radius === 'number') {\n radius = `${radius}px`;\n }\n\n if (!radius) return null;\n\n if (radius === true) radius = '1r';\n\n const processed = parseStyle(radius);\n const group = processed.groups[0] ?? makeEmptyDetails();\n const { mods } = group;\n let { values } = group;\n\n const keyword = extractCSSWideKeyword(group);\n\n if (keyword) {\n const dirMods = mods.filter((m) => DIRECTIONS.includes(m));\n\n if (!dirMods.length) {\n return { 'border-radius': keyword };\n }\n\n const result: Record<string, string> = {};\n const corners = new Set<number>();\n\n dirMods.forEach((dir) => {\n const i = DIRECTIONS.indexOf(dir);\n corners.add(i);\n corners.add((i + 1) % 4);\n });\n\n corners.forEach((i) => {\n result[RADIUS_LONGHANDS[i]] = keyword;\n });\n\n return result;\n }\n\n if (mods.includes('round')) {\n values = ['9999rem'];\n } else if (mods.includes('ellipse')) {\n values = ['50%'];\n } else if (!values.length) {\n values = [PROP];\n }\n\n if (mods.includes('leaf')) {\n values = [\n values[1] || SHARP,\n values[0] || PROP,\n values[1] || SHARP,\n values[0] || PROP,\n ];\n } else if (mods.includes('backleaf')) {\n values = [\n values[0] || PROP,\n values[1] || SHARP,\n values[0] || PROP,\n values[1] || SHARP,\n ];\n } else if (mods.length) {\n const arr = ['0', '0', '0', '0'];\n\n let flag = false;\n\n DIRECTIONS.forEach((dir, i) => {\n if (!mods.includes(dir)) return;\n\n flag = true;\n\n arr[i] = values[0] || PROP;\n arr[(i + 1) % 4] = values[0] || PROP;\n });\n\n if (flag) {\n values = arr;\n }\n }\n\n return {\n 'border-radius': values.join(' '),\n };\n}\n\nradiusStyle.__lookupStyles = ['radius'];\n"],"mappings":";;;;AAIA,MAAM,OAAO;AACb,MAAM,QAAQ;AAEd,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACD;AAED,SAAgB,YAAY,EAC1B,UAGC;AACD,KAAI,OAAO,WAAW,SACpB,UAAS,GAAG,OAAO;AAGrB,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI,WAAW,KAAM,UAAS;CAG9B,MAAM,QADY,WAAW,OAAO,CACZ,OAAO,MAAM,kBAAkB;CACvD,MAAM,EAAE,SAAS;CACjB,IAAI,EAAE,WAAW;CAEjB,MAAM,UAAU,sBAAsB,MAAM;
|
|
1
|
+
{"version":3,"file":"radius.js","names":[],"sources":["../../src/styles/radius.ts"],"sourcesContent":["import { makeEmptyDetails } from '../parser/types';\nimport { DIRECTIONS, parseStyle } from '../utils/styles';\nimport { extractCSSWideKeyword } from './shared';\n\nconst PROP = 'var(--radius)';\nconst SHARP = 'var(--sharp-radius)';\n\nconst RADIUS_LONGHANDS = [\n 'border-top-left-radius',\n 'border-top-right-radius',\n 'border-bottom-right-radius',\n 'border-bottom-left-radius',\n];\n\nexport function radiusStyle({\n radius,\n}: {\n radius?: string | number | boolean;\n}) {\n if (typeof radius === 'number') {\n radius = `${radius}px`;\n }\n\n if (!radius) return null;\n\n if (radius === true) radius = '1r';\n\n const processed = parseStyle(radius);\n const group = processed.groups[0] ?? makeEmptyDetails();\n const { mods } = group;\n let { values } = group;\n\n const keyword = extractCSSWideKeyword(group);\n\n const useLonghand = mods.includes('longhand');\n\n if (keyword) {\n const dirMods = mods.filter((m) => DIRECTIONS.includes(m));\n\n if (!dirMods.length) {\n if (useLonghand) {\n return Object.fromEntries(\n RADIUS_LONGHANDS.map((prop) => [prop, keyword]),\n );\n }\n\n return { 'border-radius': keyword };\n }\n\n const result: Record<string, string> = {};\n const corners = new Set<number>();\n\n dirMods.forEach((dir) => {\n const i = DIRECTIONS.indexOf(dir);\n corners.add(i);\n corners.add((i + 1) % 4);\n });\n\n corners.forEach((i) => {\n result[RADIUS_LONGHANDS[i]] = keyword;\n });\n\n return result;\n }\n\n if (mods.includes('round')) {\n values = ['9999rem'];\n } else if (mods.includes('ellipse')) {\n values = ['50%'];\n } else if (!values.length) {\n values = [PROP];\n }\n\n if (mods.includes('leaf')) {\n values = [\n values[1] || SHARP,\n values[0] || PROP,\n values[1] || SHARP,\n values[0] || PROP,\n ];\n } else if (mods.includes('backleaf')) {\n values = [\n values[0] || PROP,\n values[1] || SHARP,\n values[0] || PROP,\n values[1] || SHARP,\n ];\n } else if (mods.length) {\n const arr = ['0', '0', '0', '0'];\n\n let flag = false;\n\n DIRECTIONS.forEach((dir, i) => {\n if (!mods.includes(dir)) return;\n\n flag = true;\n\n arr[i] = values[0] || PROP;\n arr[(i + 1) % 4] = values[0] || PROP;\n });\n\n if (flag) {\n values = arr;\n }\n }\n\n if (useLonghand) {\n return {\n [RADIUS_LONGHANDS[0]]: values[0],\n [RADIUS_LONGHANDS[1]]: values[1] || values[0],\n [RADIUS_LONGHANDS[2]]: values[2] || values[0],\n [RADIUS_LONGHANDS[3]]: values[3] || values[1] || values[0],\n };\n }\n\n return {\n 'border-radius': values.join(' '),\n };\n}\n\nradiusStyle.__lookupStyles = ['radius'];\n"],"mappings":";;;;AAIA,MAAM,OAAO;AACb,MAAM,QAAQ;AAEd,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACD;AAED,SAAgB,YAAY,EAC1B,UAGC;AACD,KAAI,OAAO,WAAW,SACpB,UAAS,GAAG,OAAO;AAGrB,KAAI,CAAC,OAAQ,QAAO;AAEpB,KAAI,WAAW,KAAM,UAAS;CAG9B,MAAM,QADY,WAAW,OAAO,CACZ,OAAO,MAAM,kBAAkB;CACvD,MAAM,EAAE,SAAS;CACjB,IAAI,EAAE,WAAW;CAEjB,MAAM,UAAU,sBAAsB,MAAM;CAE5C,MAAM,cAAc,KAAK,SAAS,WAAW;AAE7C,KAAI,SAAS;EACX,MAAM,UAAU,KAAK,QAAQ,MAAM,WAAW,SAAS,EAAE,CAAC;AAE1D,MAAI,CAAC,QAAQ,QAAQ;AACnB,OAAI,YACF,QAAO,OAAO,YACZ,iBAAiB,KAAK,SAAS,CAAC,MAAM,QAAQ,CAAC,CAChD;AAGH,UAAO,EAAE,iBAAiB,SAAS;;EAGrC,MAAM,SAAiC,EAAE;EACzC,MAAM,0BAAU,IAAI,KAAa;AAEjC,UAAQ,SAAS,QAAQ;GACvB,MAAM,IAAI,WAAW,QAAQ,IAAI;AACjC,WAAQ,IAAI,EAAE;AACd,WAAQ,KAAK,IAAI,KAAK,EAAE;IACxB;AAEF,UAAQ,SAAS,MAAM;AACrB,UAAO,iBAAiB,MAAM;IAC9B;AAEF,SAAO;;AAGT,KAAI,KAAK,SAAS,QAAQ,CACxB,UAAS,CAAC,UAAU;UACX,KAAK,SAAS,UAAU,CACjC,UAAS,CAAC,MAAM;UACP,CAAC,OAAO,OACjB,UAAS,CAAC,KAAK;AAGjB,KAAI,KAAK,SAAS,OAAO,CACvB,UAAS;EACP,OAAO,MAAM;EACb,OAAO,MAAM;EACb,OAAO,MAAM;EACb,OAAO,MAAM;EACd;UACQ,KAAK,SAAS,WAAW,CAClC,UAAS;EACP,OAAO,MAAM;EACb,OAAO,MAAM;EACb,OAAO,MAAM;EACb,OAAO,MAAM;EACd;UACQ,KAAK,QAAQ;EACtB,MAAM,MAAM;GAAC;GAAK;GAAK;GAAK;GAAI;EAEhC,IAAI,OAAO;AAEX,aAAW,SAAS,KAAK,MAAM;AAC7B,OAAI,CAAC,KAAK,SAAS,IAAI,CAAE;AAEzB,UAAO;AAEP,OAAI,KAAK,OAAO,MAAM;AACtB,QAAK,IAAI,KAAK,KAAK,OAAO,MAAM;IAChC;AAEF,MAAI,KACF,UAAS;;AAIb,KAAI,YACF,QAAO;GACJ,iBAAiB,KAAK,OAAO;GAC7B,iBAAiB,KAAK,OAAO,MAAM,OAAO;GAC1C,iBAAiB,KAAK,OAAO,MAAM,OAAO;GAC1C,iBAAiB,KAAK,OAAO,MAAM,OAAO,MAAM,OAAO;EACzD;AAGH,QAAO,EACL,iBAAiB,OAAO,KAAK,IAAI,EAClC;;AAGH,YAAY,iBAAiB,CAAC,SAAS"}
|
package/docs/styles.md
CHANGED
|
@@ -104,6 +104,8 @@ Element padding with directional modifiers and multi-group support. Use **comma-
|
|
|
104
104
|
|
|
105
105
|
**Direction modifiers:** `top`, `right`, `bottom`, `left`
|
|
106
106
|
|
|
107
|
+
**Output modifier:** `longhand` — forces output as individual CSS longhand properties (`padding-top`, `padding-right`, `padding-bottom`, `padding-left`) instead of the `padding` shorthand. Useful when children need to selectively inherit individual directions.
|
|
108
|
+
|
|
107
109
|
| Value | Effect |
|
|
108
110
|
|-------|--------|
|
|
109
111
|
| `"2x"` | All sides `2x` |
|
|
@@ -112,6 +114,7 @@ Element padding with directional modifiers and multi-group support. Use **comma-
|
|
|
112
114
|
| `"1x left right"` | Left and right `1x`, top/bottom `0` |
|
|
113
115
|
| `"1x, 2x top"` | All sides `1x`, then top overridden to `2x` |
|
|
114
116
|
| `"1x, 2x top bottom"` | Left/right `1x`, top/bottom `2x` |
|
|
117
|
+
| `"2x longhand"` | All sides `2x`, output as 4 individual `padding-*` properties |
|
|
115
118
|
| `true` | All sides `1x` |
|
|
116
119
|
| Number | Converted to `px` |
|
|
117
120
|
|
|
@@ -129,6 +132,8 @@ Element margin. Same syntax, modifiers, and multi-group support as `padding`.
|
|
|
129
132
|
|
|
130
133
|
**Direction modifiers:** `top`, `right`, `bottom`, `left`
|
|
131
134
|
|
|
135
|
+
**Output modifier:** `longhand` — forces output as individual CSS longhand properties (`margin-top`, etc.) instead of the `margin` shorthand.
|
|
136
|
+
|
|
132
137
|
| Value | Effect |
|
|
133
138
|
|-------|--------|
|
|
134
139
|
| `"2x"` | All sides `2x` |
|
|
@@ -190,12 +195,15 @@ Positioning offsets with directional modifiers and multi-group support. Same dir
|
|
|
190
195
|
|
|
191
196
|
**Direction modifiers:** `top`, `right`, `bottom`, `left`
|
|
192
197
|
|
|
198
|
+
**Output modifier:** `longhand` — forces output as individual CSS properties (`top`, `right`, `bottom`, `left`) instead of the `inset` shorthand.
|
|
199
|
+
|
|
193
200
|
| Value | Effect |
|
|
194
201
|
|-------|--------|
|
|
195
202
|
| `"0"` | All sides `0` |
|
|
196
203
|
| `"2x top"` | Top `2x`, right/bottom/left `auto` |
|
|
197
204
|
| `"1x left right"` | Left and right `1x`, top/bottom `auto` |
|
|
198
205
|
| `"0, 2x top"` | All sides `0`, then top overridden to `2x` |
|
|
206
|
+
| `"0 longhand"` | All sides `0`, output as individual `top`/`right`/`bottom`/`left` |
|
|
199
207
|
| `true` | All sides `0` |
|
|
200
208
|
|
|
201
209
|
Later comma-separated groups override earlier groups for conflicting directions.
|
|
@@ -281,12 +289,15 @@ Border shorthand with directional and multi-group support. Use **comma-separated
|
|
|
281
289
|
|
|
282
290
|
**Direction modifiers:** `top`, `right`, `bottom`, `left`
|
|
283
291
|
|
|
292
|
+
**Output modifier:** `longhand` — forces output as individual CSS properties (`border-top`, `border-right`, `border-bottom`, `border-left`) instead of the `border` shorthand. Useful when children need to selectively inherit individual sides.
|
|
293
|
+
|
|
284
294
|
| Value | Effect |
|
|
285
295
|
|-------|--------|
|
|
286
296
|
| `true` | Default border (`1bw solid #border`) on all sides |
|
|
287
297
|
| `"2bw dashed #purple"` | All sides: 2bw dashed purple |
|
|
288
298
|
| `"2bw top"` | Top only: 2bw solid `#border`, others: 0 |
|
|
289
299
|
| `"dotted #danger left right"` | Left/right: 1bw dotted `#danger`, others: 0 |
|
|
300
|
+
| `"1bw longhand"` | All sides: 1bw solid `#border`, output as 4 individual `border-*` properties |
|
|
290
301
|
| `"1bw #red, 2bw #blue top"` | All sides: 1bw solid `#red`, top overridden to 2bw solid `#blue` |
|
|
291
302
|
| `"1bw, dashed top bottom, #purple left right"` | Base: 1bw solid `#border`, top/bottom: 1bw dashed `#border`, left/right: 1bw solid `#purple` |
|
|
292
303
|
|
|
@@ -310,6 +321,8 @@ Border radius with shape presets and directional modifiers.
|
|
|
310
321
|
|
|
311
322
|
**Direction modifiers:** `top`, `right`, `bottom`, `left` — rounds only the specified corners.
|
|
312
323
|
|
|
324
|
+
**Output modifier:** `longhand` — forces output as individual CSS longhand properties (`border-top-left-radius`, `border-top-right-radius`, `border-bottom-right-radius`, `border-bottom-left-radius`) instead of the `border-radius` shorthand. Useful when children need to selectively inherit individual corners via `radius: 'inherit left'`.
|
|
325
|
+
|
|
313
326
|
| Value | Effect |
|
|
314
327
|
|-------|--------|
|
|
315
328
|
| `"2r"` | All corners `2r` |
|
|
@@ -318,6 +331,7 @@ Border radius with shape presets and directional modifiers.
|
|
|
318
331
|
| `"1r top"` | Top-left and top-right `1r`, bottom-left and bottom-right `0` |
|
|
319
332
|
| `"leaf"` | Alternating sharp/round corners (top-left `0`, top-right `1r`, bottom-right `0`, bottom-left `1r`) |
|
|
320
333
|
| `"backleaf"` | Inverse leaf (top-left `1r`, top-right `0`, bottom-right `1r`, bottom-left `0`) |
|
|
334
|
+
| `"1r longhand"` | All corners `1r`, output as 4 individual `border-*-radius` properties |
|
|
321
335
|
| `"inherit"` | All corners inherit from parent (`border-radius: inherit`) |
|
|
322
336
|
| `"inherit right"` | Right corners inherit from parent (uses longhand properties) |
|
|
323
337
|
|
package/package.json
CHANGED