@tamagui/style-grammar 0.0.0-bootstrap.0 → 3.0.0-beta.643.1
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/LICENSE +21 -0
- package/README.md +33 -1
- package/dist/cjs/backgroundFamily.cjs +176 -0
- package/dist/cjs/backgroundFamily.native.cjs +195 -0
- package/dist/cjs/backgroundFamily.native.js +197 -0
- package/dist/cjs/backgroundFamily.native.js.map +1 -0
- package/dist/cjs/borderFamily.cjs +169 -0
- package/dist/cjs/borderFamily.native.cjs +247 -0
- package/dist/cjs/borderFamily.native.js +249 -0
- package/dist/cjs/borderFamily.native.js.map +1 -0
- package/dist/cjs/candidate.cjs +608 -0
- package/dist/cjs/candidate.native.cjs +821 -0
- package/dist/cjs/candidate.native.js +823 -0
- package/dist/cjs/candidate.native.js.map +1 -0
- package/dist/cjs/candidateTarget.cjs +50 -0
- package/dist/cjs/candidateTarget.native.cjs +88 -0
- package/dist/cjs/candidateTarget.native.js +90 -0
- package/dist/cjs/candidateTarget.native.js.map +1 -0
- package/dist/cjs/clauseCapability.cjs +130 -0
- package/dist/cjs/clauseCapability.native.cjs +152 -0
- package/dist/cjs/clauseCapability.native.js +154 -0
- package/dist/cjs/clauseCapability.native.js.map +1 -0
- package/dist/cjs/clausePrecedence.cjs +153 -0
- package/dist/cjs/clausePrecedence.native.cjs +204 -0
- package/dist/cjs/clausePrecedence.native.js +206 -0
- package/dist/cjs/clausePrecedence.native.js.map +1 -0
- package/dist/cjs/clauseSources.cjs +47 -0
- package/dist/cjs/clauseSources.native.cjs +49 -0
- package/dist/cjs/clauseSources.native.js +51 -0
- package/dist/cjs/clauseSources.native.js.map +1 -0
- package/dist/cjs/config.cjs +130 -0
- package/dist/cjs/config.native.cjs +185 -0
- package/dist/cjs/config.native.js +187 -0
- package/dist/cjs/config.native.js.map +1 -0
- package/dist/cjs/evaluateProgram.cjs +65 -0
- package/dist/cjs/evaluateProgram.native.cjs +70 -0
- package/dist/cjs/evaluateProgram.native.js +72 -0
- package/dist/cjs/evaluateProgram.native.js.map +1 -0
- package/dist/cjs/fontShorthand.cjs +207 -0
- package/dist/cjs/fontShorthand.native.cjs +260 -0
- package/dist/cjs/fontShorthand.native.js +262 -0
- package/dist/cjs/fontShorthand.native.js.map +1 -0
- package/dist/cjs/geometricShorthand.cjs +122 -0
- package/dist/cjs/geometricShorthand.native.cjs +128 -0
- package/dist/cjs/geometricShorthand.native.js +130 -0
- package/dist/cjs/geometricShorthand.native.js.map +1 -0
- package/dist/cjs/index.cjs +19 -0
- package/dist/cjs/index.native.cjs +21 -0
- package/dist/cjs/index.native.js +23 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/lowerProgram.cjs +205 -0
- package/dist/cjs/lowerProgram.native.cjs +257 -0
- package/dist/cjs/lowerProgram.native.js +259 -0
- package/dist/cjs/lowerProgram.native.js.map +1 -0
- package/dist/cjs/mergeFlatValues.cjs +50 -0
- package/dist/cjs/mergeFlatValues.native.cjs +71 -0
- package/dist/cjs/mergeFlatValues.native.js +73 -0
- package/dist/cjs/mergeFlatValues.native.js.map +1 -0
- package/dist/cjs/modifierRegistry.cjs +246 -0
- package/dist/cjs/modifierRegistry.native.cjs +426 -0
- package/dist/cjs/modifierRegistry.native.js +428 -0
- package/dist/cjs/modifierRegistry.native.js.map +1 -0
- package/dist/cjs/payloadShape.cjs +69 -0
- package/dist/cjs/payloadShape.native.cjs +71 -0
- package/dist/cjs/payloadShape.native.js +73 -0
- package/dist/cjs/payloadShape.native.js.map +1 -0
- package/dist/cjs/programEligibility.cjs +46 -0
- package/dist/cjs/programEligibility.native.cjs +48 -0
- package/dist/cjs/programEligibility.native.js +50 -0
- package/dist/cjs/programEligibility.native.js.map +1 -0
- package/dist/cjs/programHash.cjs +86 -0
- package/dist/cjs/programHash.native.cjs +106 -0
- package/dist/cjs/programHash.native.js +108 -0
- package/dist/cjs/programHash.native.js.map +1 -0
- package/dist/cjs/programs.cjs +128 -0
- package/dist/cjs/programs.native.cjs +220 -0
- package/dist/cjs/programs.native.js +222 -0
- package/dist/cjs/programs.native.js.map +1 -0
- package/dist/cjs/registry.cjs +629 -0
- package/dist/cjs/registry.native.cjs +635 -0
- package/dist/cjs/registry.native.js +637 -0
- package/dist/cjs/registry.native.js.map +1 -0
- package/dist/cjs/resolvePayload.cjs +296 -0
- package/dist/cjs/resolvePayload.native.cjs +302 -0
- package/dist/cjs/resolvePayload.native.js +304 -0
- package/dist/cjs/resolvePayload.native.js.map +1 -0
- package/dist/cjs/runtime.cjs +50 -0
- package/dist/cjs/runtime.native.cjs +52 -0
- package/dist/cjs/runtime.native.js +54 -0
- package/dist/cjs/runtime.native.js.map +1 -0
- package/dist/cjs/safeAreaVariables.cjs +42 -0
- package/dist/cjs/safeAreaVariables.native.cjs +44 -0
- package/dist/cjs/safeAreaVariables.native.js +46 -0
- package/dist/cjs/safeAreaVariables.native.js.map +1 -0
- package/dist/cjs/scanFlatValue.cjs +181 -0
- package/dist/cjs/scanFlatValue.native.cjs +183 -0
- package/dist/cjs/scanFlatValue.native.js +185 -0
- package/dist/cjs/scanFlatValue.native.js.map +1 -0
- package/dist/cjs/serializePayload.cjs +149 -0
- package/dist/cjs/serializePayload.native.cjs +187 -0
- package/dist/cjs/serializePayload.native.js +189 -0
- package/dist/cjs/serializePayload.native.js.map +1 -0
- package/dist/cjs/stateModifiers.cjs +43 -0
- package/dist/cjs/stateModifiers.native.cjs +45 -0
- package/dist/cjs/stateModifiers.native.js +47 -0
- package/dist/cjs/stateModifiers.native.js.map +1 -0
- package/dist/cjs/states.cjs +97 -0
- package/dist/cjs/states.native.cjs +131 -0
- package/dist/cjs/states.native.js +133 -0
- package/dist/cjs/states.native.js.map +1 -0
- package/dist/cjs/table.cjs +54 -0
- package/dist/cjs/table.native.cjs +135 -0
- package/dist/cjs/table.native.js +137 -0
- package/dist/cjs/table.native.js.map +1 -0
- package/dist/cjs/textDecorationFamily.cjs +129 -0
- package/dist/cjs/textDecorationFamily.native.cjs +199 -0
- package/dist/cjs/textDecorationFamily.native.js +201 -0
- package/dist/cjs/textDecorationFamily.native.js.map +1 -0
- package/dist/cjs/tooling.cjs +26 -0
- package/dist/cjs/tooling.native.cjs +28 -0
- package/dist/cjs/tooling.native.js +30 -0
- package/dist/cjs/tooling.native.js.map +1 -0
- package/dist/cjs/toolingAnnotations.cjs +105 -0
- package/dist/cjs/toolingAnnotations.native.cjs +133 -0
- package/dist/cjs/toolingAnnotations.native.js +135 -0
- package/dist/cjs/toolingAnnotations.native.js.map +1 -0
- package/dist/cjs/toolingDiagnostics.cjs +459 -0
- package/dist/cjs/toolingDiagnostics.native.cjs +788 -0
- package/dist/cjs/toolingDiagnostics.native.js +790 -0
- package/dist/cjs/toolingDiagnostics.native.js.map +1 -0
- package/dist/cjs/toolingRegistry.cjs +159 -0
- package/dist/cjs/toolingRegistry.native.cjs +164 -0
- package/dist/cjs/toolingRegistry.native.js +166 -0
- package/dist/cjs/toolingRegistry.native.js.map +1 -0
- package/dist/cjs/transformFamily.cjs +425 -0
- package/dist/cjs/transformFamily.native.cjs +517 -0
- package/dist/cjs/transformFamily.native.js +519 -0
- package/dist/cjs/transformFamily.native.js.map +1 -0
- package/dist/cjs/transition.cjs +459 -0
- package/dist/cjs/transition.native.cjs +499 -0
- package/dist/cjs/transition.native.js +501 -0
- package/dist/cjs/transition.native.js.map +1 -0
- package/dist/cjs/transitionAlign.cjs +115 -0
- package/dist/cjs/transitionAlign.native.cjs +154 -0
- package/dist/cjs/transitionAlign.native.js +156 -0
- package/dist/cjs/transitionAlign.native.js.map +1 -0
- package/dist/cjs/transitionLegacy.cjs +217 -0
- package/dist/cjs/transitionLegacy.native.cjs +260 -0
- package/dist/cjs/transitionLegacy.native.js +262 -0
- package/dist/cjs/transitionLegacy.native.js.map +1 -0
- package/dist/cjs/transitionNative.cjs +281 -0
- package/dist/cjs/transitionNative.native.cjs +285 -0
- package/dist/cjs/transitionNative.native.js +287 -0
- package/dist/cjs/transitionNative.native.js.map +1 -0
- package/dist/cjs/unitlessNumbers.cjs +86 -0
- package/dist/cjs/unitlessNumbers.native.cjs +106 -0
- package/dist/cjs/unitlessNumbers.native.js +108 -0
- package/dist/cjs/unitlessNumbers.native.js.map +1 -0
- package/dist/cjs/v6ThemeNames.cjs +47 -0
- package/dist/cjs/v6ThemeNames.native.cjs +53 -0
- package/dist/cjs/v6ThemeNames.native.js +55 -0
- package/dist/cjs/v6ThemeNames.native.js.map +1 -0
- package/dist/cjs/valueParser.cjs +148 -0
- package/dist/cjs/valueParser.native.cjs +150 -0
- package/dist/cjs/valueParser.native.js +152 -0
- package/dist/cjs/valueParser.native.js.map +1 -0
- package/dist/cjs/valueTypes.cjs +38 -0
- package/dist/cjs/valueTypes.native.cjs +40 -0
- package/dist/cjs/valueTypes.native.js +42 -0
- package/dist/cjs/valueTypes.native.js.map +1 -0
- package/dist/esm/backgroundFamily.mjs +150 -0
- package/dist/esm/backgroundFamily.mjs.map +1 -0
- package/dist/esm/backgroundFamily.native.js +167 -0
- package/dist/esm/backgroundFamily.native.js.map +1 -0
- package/dist/esm/borderFamily.mjs +146 -0
- package/dist/esm/borderFamily.mjs.map +1 -0
- package/dist/esm/borderFamily.native.js +222 -0
- package/dist/esm/borderFamily.native.js.map +1 -0
- package/dist/esm/candidate.mjs +581 -0
- package/dist/esm/candidate.mjs.map +1 -0
- package/dist/esm/candidate.native.js +792 -0
- package/dist/esm/candidate.native.js.map +1 -0
- package/dist/esm/candidateTarget.mjs +29 -0
- package/dist/esm/candidateTarget.mjs.map +1 -0
- package/dist/esm/candidateTarget.native.js +65 -0
- package/dist/esm/candidateTarget.native.js.map +1 -0
- package/dist/esm/clauseCapability.mjs +107 -0
- package/dist/esm/clauseCapability.mjs.map +1 -0
- package/dist/esm/clauseCapability.native.js +127 -0
- package/dist/esm/clauseCapability.native.js.map +1 -0
- package/dist/esm/clausePrecedence.mjs +121 -0
- package/dist/esm/clausePrecedence.mjs.map +1 -0
- package/dist/esm/clausePrecedence.native.js +170 -0
- package/dist/esm/clausePrecedence.native.js.map +1 -0
- package/dist/esm/clauseSources.mjs +23 -0
- package/dist/esm/clauseSources.mjs.map +1 -0
- package/dist/esm/clauseSources.native.js +23 -0
- package/dist/esm/clauseSources.native.js.map +1 -0
- package/dist/esm/config.mjs +103 -0
- package/dist/esm/config.mjs.map +1 -0
- package/dist/esm/config.native.js +156 -0
- package/dist/esm/config.native.js.map +1 -0
- package/dist/esm/evaluateProgram.mjs +45 -0
- package/dist/esm/evaluateProgram.mjs.map +1 -0
- package/dist/esm/evaluateProgram.native.js +48 -0
- package/dist/esm/evaluateProgram.native.js.map +1 -0
- package/dist/esm/fontShorthand.mjs +184 -0
- package/dist/esm/fontShorthand.mjs.map +1 -0
- package/dist/esm/fontShorthand.native.js +235 -0
- package/dist/esm/fontShorthand.native.js.map +1 -0
- package/dist/esm/geometricShorthand.mjs +102 -0
- package/dist/esm/geometricShorthand.mjs.map +1 -0
- package/dist/esm/geometricShorthand.native.js +106 -0
- package/dist/esm/geometricShorthand.native.js.map +1 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.native.js +1 -0
- package/dist/esm/lowerProgram.mjs +182 -0
- package/dist/esm/lowerProgram.mjs.map +1 -0
- package/dist/esm/lowerProgram.native.js +232 -0
- package/dist/esm/lowerProgram.native.js.map +1 -0
- package/dist/esm/mergeFlatValues.mjs +27 -0
- package/dist/esm/mergeFlatValues.mjs.map +1 -0
- package/dist/esm/mergeFlatValues.native.js +46 -0
- package/dist/esm/mergeFlatValues.native.js.map +1 -0
- package/dist/esm/modifierRegistry.mjs +219 -0
- package/dist/esm/modifierRegistry.mjs.map +1 -0
- package/dist/esm/modifierRegistry.native.js +397 -0
- package/dist/esm/modifierRegistry.native.js.map +1 -0
- package/dist/esm/payloadShape.mjs +49 -0
- package/dist/esm/payloadShape.mjs.map +1 -0
- package/dist/esm/payloadShape.native.js +49 -0
- package/dist/esm/payloadShape.native.js.map +1 -0
- package/dist/esm/programEligibility.mjs +22 -0
- package/dist/esm/programEligibility.mjs.map +1 -0
- package/dist/esm/programEligibility.native.js +22 -0
- package/dist/esm/programEligibility.native.js.map +1 -0
- package/dist/esm/programHash.mjs +62 -0
- package/dist/esm/programHash.mjs.map +1 -0
- package/dist/esm/programHash.native.js +80 -0
- package/dist/esm/programHash.native.js.map +1 -0
- package/dist/esm/programs.mjs +103 -0
- package/dist/esm/programs.mjs.map +1 -0
- package/dist/esm/programs.native.js +193 -0
- package/dist/esm/programs.native.js.map +1 -0
- package/dist/esm/registry.mjs +595 -0
- package/dist/esm/registry.mjs.map +1 -0
- package/dist/esm/registry.native.js +599 -0
- package/dist/esm/registry.native.js.map +1 -0
- package/dist/esm/resolvePayload.mjs +273 -0
- package/dist/esm/resolvePayload.mjs.map +1 -0
- package/dist/esm/resolvePayload.native.js +277 -0
- package/dist/esm/resolvePayload.native.js.map +1 -0
- package/dist/esm/runtime.mjs +63 -0
- package/dist/esm/runtime.native.js +63 -0
- package/dist/esm/safeAreaVariables.mjs +18 -0
- package/dist/esm/safeAreaVariables.mjs.map +1 -0
- package/dist/esm/safeAreaVariables.native.js +18 -0
- package/dist/esm/safeAreaVariables.native.js.map +1 -0
- package/dist/esm/scanFlatValue.mjs +160 -0
- package/dist/esm/scanFlatValue.mjs.map +1 -0
- package/dist/esm/scanFlatValue.native.js +160 -0
- package/dist/esm/scanFlatValue.native.js.map +1 -0
- package/dist/esm/serializePayload.mjs +125 -0
- package/dist/esm/serializePayload.mjs.map +1 -0
- package/dist/esm/serializePayload.native.js +161 -0
- package/dist/esm/serializePayload.native.js.map +1 -0
- package/dist/esm/stateModifiers.mjs +19 -0
- package/dist/esm/stateModifiers.mjs.map +1 -0
- package/dist/esm/stateModifiers.native.js +19 -0
- package/dist/esm/stateModifiers.native.js.map +1 -0
- package/dist/esm/states.mjs +69 -0
- package/dist/esm/states.mjs.map +1 -0
- package/dist/esm/states.native.js +101 -0
- package/dist/esm/states.native.js.map +1 -0
- package/dist/esm/table.mjs +31 -0
- package/dist/esm/table.mjs.map +1 -0
- package/dist/esm/table.native.js +110 -0
- package/dist/esm/table.native.js.map +1 -0
- package/dist/esm/textDecorationFamily.mjs +106 -0
- package/dist/esm/textDecorationFamily.mjs.map +1 -0
- package/dist/esm/textDecorationFamily.native.js +174 -0
- package/dist/esm/textDecorationFamily.native.js.map +1 -0
- package/dist/esm/tooling.mjs +15 -0
- package/dist/esm/tooling.native.js +15 -0
- package/dist/esm/toolingAnnotations.mjs +85 -0
- package/dist/esm/toolingAnnotations.mjs.map +1 -0
- package/dist/esm/toolingAnnotations.native.js +111 -0
- package/dist/esm/toolingAnnotations.native.js.map +1 -0
- package/dist/esm/toolingDiagnostics.mjs +428 -0
- package/dist/esm/toolingDiagnostics.mjs.map +1 -0
- package/dist/esm/toolingDiagnostics.native.js +755 -0
- package/dist/esm/toolingDiagnostics.native.js.map +1 -0
- package/dist/esm/toolingRegistry.mjs +135 -0
- package/dist/esm/toolingRegistry.mjs.map +1 -0
- package/dist/esm/toolingRegistry.native.js +138 -0
- package/dist/esm/toolingRegistry.native.js.map +1 -0
- package/dist/esm/transformFamily.mjs +392 -0
- package/dist/esm/transformFamily.mjs.map +1 -0
- package/dist/esm/transformFamily.native.js +482 -0
- package/dist/esm/transformFamily.native.js.map +1 -0
- package/dist/esm/transition.mjs +434 -0
- package/dist/esm/transition.mjs.map +1 -0
- package/dist/esm/transition.native.js +472 -0
- package/dist/esm/transition.native.js.map +1 -0
- package/dist/esm/transitionAlign.mjs +95 -0
- package/dist/esm/transitionAlign.mjs.map +1 -0
- package/dist/esm/transitionAlign.native.js +132 -0
- package/dist/esm/transitionAlign.native.js.map +1 -0
- package/dist/esm/transitionLegacy.mjs +197 -0
- package/dist/esm/transitionLegacy.mjs.map +1 -0
- package/dist/esm/transitionLegacy.native.js +238 -0
- package/dist/esm/transitionLegacy.native.js.map +1 -0
- package/dist/esm/transitionNative.mjs +257 -0
- package/dist/esm/transitionNative.mjs.map +1 -0
- package/dist/esm/transitionNative.native.js +259 -0
- package/dist/esm/transitionNative.native.js.map +1 -0
- package/dist/esm/unitlessNumbers.mjs +65 -0
- package/dist/esm/unitlessNumbers.mjs.map +1 -0
- package/dist/esm/unitlessNumbers.native.js +83 -0
- package/dist/esm/unitlessNumbers.native.js.map +1 -0
- package/dist/esm/v6ThemeNames.mjs +23 -0
- package/dist/esm/v6ThemeNames.mjs.map +1 -0
- package/dist/esm/v6ThemeNames.native.js +27 -0
- package/dist/esm/v6ThemeNames.native.js.map +1 -0
- package/dist/esm/valueParser.mjs +125 -0
- package/dist/esm/valueParser.mjs.map +1 -0
- package/dist/esm/valueParser.native.js +125 -0
- package/dist/esm/valueParser.native.js.map +1 -0
- package/dist/esm/valueTypes.mjs +14 -0
- package/dist/esm/valueTypes.mjs.map +1 -0
- package/dist/esm/valueTypes.native.js +14 -0
- package/dist/esm/valueTypes.native.js.map +1 -0
- package/package.json +98 -4
- package/src/backgroundFamily.ts +182 -0
- package/src/borderFamily.ts +172 -0
- package/src/candidate.ts +691 -0
- package/src/candidateTarget.ts +67 -0
- package/src/clauseCapability.ts +209 -0
- package/src/clausePrecedence.ts +198 -0
- package/src/clauseSources.ts +29 -0
- package/src/config.ts +169 -0
- package/src/evaluateProgram.ts +91 -0
- package/src/fontShorthand.ts +177 -0
- package/src/geometricShorthand.ts +105 -0
- package/src/index.ts +1 -0
- package/src/lowerProgram.ts +398 -0
- package/src/modifierRegistry.ts +340 -0
- package/src/payloadShape.ts +92 -0
- package/src/programEligibility.ts +46 -0
- package/src/programHash.ts +128 -0
- package/src/programs.ts +95 -0
- package/src/registry.ts +367 -0
- package/src/resolvePayload.ts +480 -0
- package/src/runtime.ts +32 -0
- package/src/safeAreaVariables.ts +19 -0
- package/src/scanFlatValue.ts +327 -0
- package/src/serializePayload.ts +199 -0
- package/src/stateModifiers.ts +36 -0
- package/src/states.ts +128 -0
- package/src/table.ts +47 -0
- package/src/textDecorationFamily.ts +119 -0
- package/src/tooling.ts +8 -0
- package/src/toolingAnnotations.ts +151 -0
- package/src/toolingDiagnostics.ts +735 -0
- package/src/toolingRegistry.ts +130 -0
- package/src/transformFamily.ts +590 -0
- package/src/transition.ts +553 -0
- package/src/transitionAlign.ts +165 -0
- package/src/transitionLegacy.ts +237 -0
- package/src/transitionNative.ts +357 -0
- package/src/unitlessNumbers.ts +61 -0
- package/src/v6ThemeNames.ts +40 -0
- package/src/valueParser.ts +193 -0
- package/src/valueTypes.ts +136 -0
- package/types/backgroundFamily.d.ts +17 -0
- package/types/backgroundFamily.d.ts.map +11 -0
- package/types/borderFamily.d.ts +23 -0
- package/types/borderFamily.d.ts.map +11 -0
- package/types/candidate.d.ts +52 -0
- package/types/candidate.d.ts.map +11 -0
- package/types/candidateTarget.d.ts +32 -0
- package/types/candidateTarget.d.ts.map +11 -0
- package/types/clauseCapability.d.ts +69 -0
- package/types/clauseCapability.d.ts.map +11 -0
- package/types/clausePrecedence.d.ts +30 -0
- package/types/clausePrecedence.d.ts.map +11 -0
- package/types/clauseSources.d.ts +12 -0
- package/types/clauseSources.d.ts.map +11 -0
- package/types/config.d.ts +44 -0
- package/types/config.d.ts.map +11 -0
- package/types/evaluateProgram.d.ts +27 -0
- package/types/evaluateProgram.d.ts.map +11 -0
- package/types/fontShorthand.d.ts +25 -0
- package/types/fontShorthand.d.ts.map +11 -0
- package/types/geometricShorthand.d.ts +21 -0
- package/types/geometricShorthand.d.ts.map +11 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +11 -0
- package/types/lowerProgram.d.ts +73 -0
- package/types/lowerProgram.d.ts.map +11 -0
- package/types/mergeFlatValues.d.ts +14 -0
- package/types/mergeFlatValues.d.ts.map +11 -0
- package/types/modifierRegistry.d.ts +70 -0
- package/types/modifierRegistry.d.ts.map +11 -0
- package/types/payloadShape.d.ts +15 -0
- package/types/payloadShape.d.ts.map +11 -0
- package/types/programEligibility.d.ts +23 -0
- package/types/programEligibility.d.ts.map +11 -0
- package/types/programHash.d.ts +20 -0
- package/types/programHash.d.ts.map +11 -0
- package/types/programs.d.ts +18 -0
- package/types/programs.d.ts.map +11 -0
- package/types/registry.d.ts +24 -0
- package/types/registry.d.ts.map +11 -0
- package/types/resolvePayload.d.ts +75 -0
- package/types/resolvePayload.d.ts.map +11 -0
- package/types/runtime.d.ts +34 -0
- package/types/runtime.d.ts.map +11 -0
- package/types/safeAreaVariables.d.ts +5 -0
- package/types/safeAreaVariables.d.ts.map +11 -0
- package/types/scanFlatValue.d.ts +29 -0
- package/types/scanFlatValue.d.ts.map +11 -0
- package/types/serializePayload.d.ts +13 -0
- package/types/serializePayload.d.ts.map +11 -0
- package/types/stateModifiers.d.ts +14 -0
- package/types/stateModifiers.d.ts.map +11 -0
- package/types/states.d.ts +22 -0
- package/types/states.d.ts.map +11 -0
- package/types/table.d.ts +4 -0
- package/types/table.d.ts.map +11 -0
- package/types/textDecorationFamily.d.ts +23 -0
- package/types/textDecorationFamily.d.ts.map +11 -0
- package/types/tooling.d.ts +10 -0
- package/types/tooling.d.ts.map +11 -0
- package/types/toolingAnnotations.d.ts +29 -0
- package/types/toolingAnnotations.d.ts.map +11 -0
- package/types/toolingDiagnostics.d.ts +114 -0
- package/types/toolingDiagnostics.d.ts.map +11 -0
- package/types/toolingRegistry.d.ts +10 -0
- package/types/toolingRegistry.d.ts.map +11 -0
- package/types/transformFamily.d.ts +83 -0
- package/types/transformFamily.d.ts.map +11 -0
- package/types/transition.d.ts +65 -0
- package/types/transition.d.ts.map +11 -0
- package/types/transitionAlign.d.ts +15 -0
- package/types/transitionAlign.d.ts.map +11 -0
- package/types/transitionLegacy.d.ts +9 -0
- package/types/transitionLegacy.d.ts.map +11 -0
- package/types/transitionNative.d.ts +41 -0
- package/types/transitionNative.d.ts.map +11 -0
- package/types/unitlessNumbers.d.ts +3 -0
- package/types/unitlessNumbers.d.ts.map +11 -0
- package/types/v6ThemeNames.d.ts +7 -0
- package/types/v6ThemeNames.d.ts.map +11 -0
- package/types/valueParser.d.ts +36 -0
- package/types/valueParser.d.ts.map +11 -0
- package/types/valueTypes.d.ts +66 -0
- package/types/valueTypes.d.ts.map +11 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAuBA,cAAc,cAAc,4BAA4B;AAYxD,iBAAiB,iBAAiB;;CAEhC;;CAEA;;CAEA;;;;;;;AAUF,OAAO,iBAAS,iBACd,kBACA,MAAM,2BACL;;AAwCH,YAAY,oBAAoB,WAAW,QAAQ;;;;;AAMnD,iBAAiB,SAAS;;CAExB,QAAQ;;CAER;;AAGF,iBAAiB,iBAAiB;CAChC,WAAW,aAAa,WAAW;CACnC;CACA;;CAEA;;AAGF,iBAAiB,qBAAqB;;;;;;;;;;;CAWpC,SAAS,UAAU,qBAAqB,iBAAiB;CACzD,kBAAkB;;AAGpB,iBAAiB,gBAAgB;CAC/B;;CAEA;CACA,SAAS;;;;;;CAMT,OAAO;;;;;;;;AAWT,OAAO,iBAAS,qBACd,OAAO,iBACP,UAAU,uBACT",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/clauseCapability.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"// The platform-clause capability contract and the composed conversion\n// assessment (three-dimension review, 2026-07-31).\n//\n// Three separately-owned dimensions, one composed answer:\n// - PROPERTY: programEligibility (can this prop carry programs at all).\n// - CLAUSE (this file): can a modifier lower on web CSS, and can it evaluate\n// natively. This is the ONE owner of both capability sets — the web side is\n// DERIVED from the lowering selector table and the native side is defined\n// here and consumed by the native evaluator, so the claims cannot drift\n// from what actually runs.\n// - HOST: owned by the validStyles tables in @tamagui/helpers (enforced at\n// runtime by the text-only-prop ruling). NOT mirrored here — the consumer\n// supplies a HostView it already holds (staticConfig for the runtime and\n// codemod, the serialized config for tooling).\n//\n// The composition lives INSIDE assessFlatConversion so no consumer ever\n// combines axes itself: one question, one structured answer, and \"clean\"\n// means convertible AND evaluable where the author put it.\n\nimport { legacyPartComposite, programEligibility } from './programEligibility'\nimport { defaultStateSelectors } from './lowerProgram'\nimport { parseContainerModifier, parseGroupModifier } from './modifierRegistry'\nimport { nativeGroupSourceableStates, nativeSourceableStates } from './clauseSources'\nimport type { ModifierKind, ModifierRegistryView } from './valueTypes'\n\nconst nativeGroupSourceable: ReadonlySet<string> = new Set(nativeGroupSourceableStates)\n\n/**\n * Web lowerability is DERIVED from the selector table the lowering actually\n * uses, including the lifecycle classes emitted by createComponent.\n */\nconst webLowerableStates: ReadonlySet<string> = new Set(\n Object.keys(defaultStateSelectors)\n)\n\nexport interface ClauseCapability {\n /** the clause can lower to web CSS */\n web: boolean\n /** the clause can evaluate on native */\n native: boolean\n /** why a side is unsupported, for diagnostics */\n note?: string\n}\n\nconst bothTargets: ClauseCapability = Object.freeze({ web: true, native: true })\n\n/**\n * Per-modifier capability. `kind` comes from the same registry the value was\n * parsed against; an unregistered modifier is a parse error upstream and\n * reports unsupported on both targets here.\n */\nexport function clauseCapability(\n modifier: string,\n kind: ModifierKind | undefined\n): ClauseCapability {\n if (kind === 'media' || kind === 'theme' || kind === 'platform') {\n return bothTargets\n }\n if (kind === 'container') {\n return bothTargets\n }\n if (kind === 'state') {\n const web = webLowerableStates.has(modifier)\n const native = nativeSourceableStates.has(modifier)\n if (web && native) return bothTargets\n return {\n web,\n native,\n note: !web\n ? `\"${modifier}:\" cannot lower to web CSS because it has no selector`\n : `\"${modifier}:\" is a component-tier state with no native source until the behavior packages feed componentState`,\n }\n }\n if (kind === 'group') {\n const parsed = parseGroupModifier(modifier)\n if (!parsed)\n return { web: false, native: false, note: `\"${modifier}:\" is not a group modifier` }\n const web = webLowerableStates.has(parsed.state)\n const native = nativeGroupSourceable.has(parsed.state)\n if (web && native) return bothTargets\n return {\n web,\n native,\n note: `group state \"${parsed.state}\" has no native source`,\n }\n }\n return {\n web: false,\n native: false,\n note: `\"${modifier}:\" is not a registered modifier`,\n }\n}\n\n/** file-extension intent: shared files must support BOTH targets */\nexport type ConversionTargets = 'shared' | 'web' | 'native'\n\n/**\n * Host validity as the consumer already holds it — a projection of the\n * component's staticConfig, never a table of this package's own.\n */\nexport interface HostView {\n /** does this host accept `prop` as a style (validStyles + accept) */\n accepts(prop: string): boolean\n /** for diagnostics: the component label the author sees */\n displayName?: string\n}\n\nexport interface ConversionReason {\n dimension: 'property' | 'clause' | 'host'\n modifier?: string\n message: string\n /** the action the author takes, stated concretely */\n remedy: string\n}\n\nexport interface ConversionAssessment {\n /**\n * clean: convertible AND evaluable where authored, with ALL THREE\n * dimensions verified — clean is a promise, so an unchecked dimension can\n * never produce it. needs-relocation: the conversion is syntactically\n * right but this site was DETERMINED unable to evaluate it — the remedy\n * names where it goes. unknown-host: property and clauses verified but the\n * component identity could not be established, so host validity is\n * UNVERIFIED rather than fine — the site needs review, not relocation.\n * ineligible: this property cannot carry the clause spelling at all.\n */\n verdict: 'clean' | 'needs-relocation' | 'unknown-host' | 'ineligible'\n reasons: readonly ConversionReason[]\n}\n\nexport interface ConversionInput {\n property: string\n /** modifiers used across the value's clauses, deduplicated by the caller or not */\n modifiers?: readonly string[]\n targets: ConversionTargets\n /**\n * absent means the consumer could NOT establish the component's identity\n * (structural provenance proves only direct View/Text and traceable styled\n * bases today) — the verdict is then at best 'unknown-host', never 'clean'\n */\n host?: HostView\n}\n\nconst clean: ConversionAssessment = Object.freeze({ verdict: 'clean', reasons: [] })\n\n/**\n * The one call a converter, lint rule, or report makes before claiming a\n * flat-value suggestion is safe. Composes property eligibility, per-target\n * clause capability, and host validity; consumers never combine axes\n * themselves.\n */\nexport function assessFlatConversion(\n input: ConversionInput,\n registry: ModifierRegistryView\n): ConversionAssessment {\n const reasons: ConversionReason[] = []\n\n if (programEligibility(input.property) === 'legacy-part') {\n reasons.push({\n dimension: 'property',\n message: `\"${input.property}\" is a part prop with no flat clause spelling`,\n remedy: `move the condition onto \\`${legacyPartComposite[input.property]}\\``,\n })\n return { verdict: 'ineligible', reasons }\n }\n\n for (const modifier of input.modifiers ?? []) {\n const capability = clauseCapability(modifier, registry.get(modifier))\n const needsWeb = input.targets !== 'native'\n const needsNative = input.targets !== 'web'\n if ((needsWeb && !capability.web) || (needsNative && !capability.native)) {\n const missing = needsWeb && !capability.web ? 'web' : 'native'\n reasons.push({\n dimension: 'clause',\n modifier,\n message: capability.note ?? `\"${modifier}:\" is not supported on ${missing}`,\n remedy:\n missing === 'web'\n ? `keep the driver-evaluated pseudo prop, or move this usage to a .native.tsx file`\n : `move this usage to a .web.tsx file, or drop the clause on native`,\n })\n }\n }\n\n if (input.host && !input.host.accepts(input.property)) {\n reasons.push({\n dimension: 'host',\n message: `\"${input.property}\" is not a valid style on ${input.host.displayName ?? 'this component'} — the runtime drops it`,\n remedy: `move this style to a component that accepts it (a Text-based component, or html.* on web)`,\n })\n }\n\n if (reasons.length) return { verdict: 'needs-relocation', reasons }\n\n if (!input.host) {\n return {\n verdict: 'unknown-host',\n reasons: [\n {\n dimension: 'host',\n message: `the component's identity could not be established, so host validity for \"${input.property}\" is unverified`,\n remedy: `verify the component accepts this style prop, or supply type-aware provenance so the check can run`,\n },\n ],\n }\n }\n\n return clean\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { canonicalClauseModifier } from "./modifierRegistry";
|
|
2
|
+
import { type ModifierKind, type ModifierRegistryView } from "./valueTypes";
|
|
3
|
+
export { grammarMaxNonPlatformDepth } from "./valueTypes";
|
|
4
|
+
/**
|
|
5
|
+
* The CSS emitter deliberately caps a condition chain at five distinct
|
|
6
|
+
* non-platform conditions. The parser can represent longer chains, but they
|
|
7
|
+
* cannot be lowered while also giving platform clauses a finite specificity
|
|
8
|
+
* floor above every platform-less clause, so the shared comparator rejects
|
|
9
|
+
* them consistently on every surface.
|
|
10
|
+
*/
|
|
11
|
+
export type ClausePrecedenceKey = readonly [platformRank: number, depth: number, categoryRank: number, withinCategoryRank: number];
|
|
12
|
+
export type OrderedModifierNames = readonly string[] | ReadonlySet<string> | Readonly<Record<string, unknown>>;
|
|
13
|
+
export type ClausePrecedenceOrder = ReadonlyMap<string, number>;
|
|
14
|
+
export declare function createClausePrecedenceOrder(names: OrderedModifierNames | undefined): ClausePrecedenceOrder;
|
|
15
|
+
/** Order-insensitive set key used by every clause merge/emission slot. */
|
|
16
|
+
export declare function clauseConditionSetKey(modifiers: readonly string[]): string;
|
|
17
|
+
export declare function getClausePrecedenceKeyFromKinds(modifiers: readonly string[], kinds: readonly (ModifierKind | undefined)[], order: ClausePrecedenceOrder): ClausePrecedenceKey;
|
|
18
|
+
export declare function getClausePrecedenceKey(modifiers: readonly string[], registry: ModifierRegistryView, order: ClausePrecedenceOrder): ClausePrecedenceKey;
|
|
19
|
+
/** Ascending comparator: a positive result means `left` wins over `right`. */
|
|
20
|
+
export declare function compareClausePrecedence(left: ClausePrecedenceKey, right: ClausePrecedenceKey): number;
|
|
21
|
+
/** Target CSS class specificity, excluding IDs/elements: (0, result, 0). */
|
|
22
|
+
export declare function clauseTargetClassSpecificity(key: ClausePrecedenceKey): number;
|
|
23
|
+
/**
|
|
24
|
+
* Subject-class repetitions needed after self-state selectors contribute
|
|
25
|
+
* their pseudo/attribute specificity naturally. Theme and group scopes use
|
|
26
|
+
* :where(), while media/container wrappers contribute zero.
|
|
27
|
+
*/
|
|
28
|
+
export declare function clauseSubjectClassRepetitions(key: ClausePrecedenceKey, selfStateSpecificity: number): number;
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=clausePrecedence.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAOA,SAAS,+BAA+B;AACxC,cAEO,mBACA,4BACA;AAEP,SAAS,kCAAkC;;;;;;;;AAS3C,YAAY,gCAEV,sBAEA,eAEA,sBAEA;AAGF,YAAY,2CAER,sBACA,SAAS;AAEb,YAAY,wBAAwB;AAgCpC,OAAO,iBAAS,4BACd,OAAO,mCACN;;AAmCH,OAAO,iBAAS,sBAAsB;AAOtC,OAAO,iBAAS,gCACd,8BACA,iBAAiB,6BACjB,OAAO,wBACN;AAuCH,OAAO,iBAAS,uBACd,8BACA,UAAU,sBACV,OAAO,wBACN;;AASH,OAAO,iBAAS,wBACd,MAAM,qBACN,OAAO;;AAUT,OAAO,iBAAS,6BAA6B,KAAK;;;;;;AASlD,OAAO,iBAAS,8BACd,KAAK,qBACL",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/clausePrecedence.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"import { grammarPlatformRank } from './config'\nimport {\n canonicalClauseModifier,\n parseContainerModifier,\n parseGroupModifier,\n} from './modifierRegistry'\n\nexport { canonicalClauseModifier } from './modifierRegistry'\nimport {\n grammarMaxNonPlatformDepth,\n type ModifierKind,\n type ModifierRegistryView,\n} from './valueTypes'\n\nexport { grammarMaxNonPlatformDepth } from './valueTypes'\n\n/**\n * The CSS emitter deliberately caps a condition chain at five distinct\n * non-platform conditions. The parser can represent longer chains, but they\n * cannot be lowered while also giving platform clauses a finite specificity\n * floor above every platform-less clause, so the shared comparator rejects\n * them consistently on every surface.\n */\nexport type ClausePrecedenceKey = readonly [\n /** no platform = 0; web/native = 1; ios/android/tv = 2; tvos/androidtv = 3 */\n platformRank: number,\n /** number of distinct non-platform conditions */\n depth: number,\n /** media < container < theme < group < state */\n categoryRank: number,\n /** declaration/lifecycle rank inside the highest category */\n withinCategoryRank: number,\n]\n\nexport type OrderedModifierNames =\n | readonly string[]\n | ReadonlySet<string>\n | Readonly<Record<string, unknown>>\n\nexport type ClausePrecedenceOrder = ReadonlyMap<string, number>\n\nconst categoryRanks: Readonly<Record<Exclude<ModifierKind, 'platform'>, number>> = {\n media: 0,\n container: 1,\n theme: 2,\n group: 3,\n state: 4,\n}\n\n// Later lifecycle entries win. Component-tier states follow the interaction\n// states in the order of states.ts's component vocabulary.\nconst stateRanks: Readonly<Record<string, number>> = Object.freeze({\n hover: 0,\n 'focus-within': 1,\n focus: 2,\n 'focus-visible': 3,\n press: 4,\n active: 4,\n pressed: 4,\n disabled: 5,\n enter: 6,\n starting: 6,\n exit: 7,\n ending: 7,\n open: 8,\n checked: 9,\n highlighted: 10,\n selected: 11,\n invalid: 12,\n})\n\nexport function createClausePrecedenceOrder(\n names: OrderedModifierNames | undefined\n): ClausePrecedenceOrder {\n const ranks = new Map<string, number>()\n if (!names) return ranks\n let rank = 0\n if (Array.isArray(names)) {\n for (const name of names) ranks.set(name, rank++)\n } else if (names instanceof Set) {\n for (const name of names) ranks.set(name, rank++)\n } else {\n for (const name in names as Readonly<Record<string, unknown>>) {\n ranks.set(name, rank++)\n }\n }\n return ranks\n}\n\nfunction withinCategoryRank(\n modifier: string,\n kind: Exclude<ModifierKind, 'platform'>,\n order: ClausePrecedenceOrder\n): number {\n if (kind === 'media') return order.get(modifier) ?? 0\n if (kind === 'container') {\n const container = parseContainerModifier(modifier)\n return container ? (order.get(container.size) ?? 0) : 0\n }\n if (kind === 'theme') return 0\n if (kind === 'group') {\n const group = parseGroupModifier(modifier)\n return group ? (stateRanks[group.state] ?? 0) : 0\n }\n return stateRanks[modifier] ?? 0\n}\n\n/** Order-insensitive set key used by every clause merge/emission slot. */\nexport function clauseConditionSetKey(modifiers: readonly string[]): string {\n if (modifiers.length === 0) return ''\n if (modifiers.length === 1) return canonicalClauseModifier(modifiers[0])\n const unique = new Set(modifiers.map(canonicalClauseModifier))\n return [...unique].sort().join(':')\n}\n\nexport function getClausePrecedenceKeyFromKinds(\n modifiers: readonly string[],\n kinds: readonly (ModifierKind | undefined)[],\n order: ClausePrecedenceOrder\n): ClausePrecedenceKey {\n let platformRank = 0\n let categoryRank = 0\n let highestWithinCategoryRank = 0\n const nonPlatform = new Set<string>()\n\n for (let index = 0; index < modifiers.length; index++) {\n const modifier = canonicalClauseModifier(modifiers[index])\n const kind = kinds[index]\n if (!kind) continue\n if (kind === 'platform') {\n platformRank = Math.max(platformRank, grammarPlatformRank(modifier))\n continue\n }\n\n nonPlatform.add(modifier)\n const nextCategoryRank = categoryRanks[kind]\n const nextWithinCategoryRank = withinCategoryRank(modifier, kind, order)\n if (nextCategoryRank > categoryRank) {\n categoryRank = nextCategoryRank\n highestWithinCategoryRank = nextWithinCategoryRank\n } else if (nextCategoryRank === categoryRank) {\n highestWithinCategoryRank = Math.max(\n highestWithinCategoryRank,\n nextWithinCategoryRank\n )\n }\n }\n\n const depth = nonPlatform.size\n if (depth > grammarMaxNonPlatformDepth) {\n throw new Error(\n `a flat value clause supports at most ${grammarMaxNonPlatformDepth} non-platform conditions; received ${depth} in \"${modifiers.join(':')}:\"`\n )\n }\n\n return [platformRank, depth, categoryRank, highestWithinCategoryRank]\n}\n\nexport function getClausePrecedenceKey(\n modifiers: readonly string[],\n registry: ModifierRegistryView,\n order: ClausePrecedenceOrder\n): ClausePrecedenceKey {\n const kinds: (ModifierKind | undefined)[] = []\n for (let index = 0; index < modifiers.length; index++) {\n kinds.push(registry.get(modifiers[index]))\n }\n return getClausePrecedenceKeyFromKinds(modifiers, kinds, order)\n}\n\n/** Ascending comparator: a positive result means `left` wins over `right`. */\nexport function compareClausePrecedence(\n left: ClausePrecedenceKey,\n right: ClausePrecedenceKey\n): number {\n for (let index = 0; index < 4; index++) {\n const difference = left[index] - right[index]\n if (difference) return difference\n }\n return 0\n}\n\n/** Target CSS class specificity, excluding IDs/elements: (0, result, 0). */\nexport function clauseTargetClassSpecificity(key: ClausePrecedenceKey): number {\n return 1 + key[1] + key[0] * (grammarMaxNonPlatformDepth + 1)\n}\n\n/**\n * Subject-class repetitions needed after self-state selectors contribute\n * their pseudo/attribute specificity naturally. Theme and group scopes use\n * :where(), while media/container wrappers contribute zero.\n */\nexport function clauseSubjectClassRepetitions(\n key: ClausePrecedenceKey,\n selfStateSpecificity: number\n): number {\n return clauseTargetClassSpecificity(key) - selfStateSpecificity\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* states the native evaluator can source from component state and lifecycle.
|
|
3
|
+
* component-tier states stay web-only until their behavior packages feed them
|
|
4
|
+
* into component state.
|
|
5
|
+
*/
|
|
6
|
+
export declare const nativeSourceableStates: ReadonlySet<string>;
|
|
7
|
+
/**
|
|
8
|
+
* states a group clause can source natively through componentState.group.
|
|
9
|
+
*/
|
|
10
|
+
export declare const nativeGroupSourceableStates: readonly string[];
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=clauseSources.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": ";;;;;AAKA,OAAO,cAAM,wBAAwB;;;;AAerC,OAAO,cAAM",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/clauseSources.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"/**\n * states the native evaluator can source from component state and lifecycle.\n * component-tier states stay web-only until their behavior packages feed them\n * into component state.\n */\nexport const nativeSourceableStates: ReadonlySet<string> = new Set([\n 'hover',\n 'press',\n 'active',\n 'focus',\n 'focus-visible',\n 'focus-within',\n 'disabled',\n 'enter',\n 'exit',\n])\n\n/**\n * states a group clause can source natively through componentState.group.\n */\nexport const nativeGroupSourceableStates: readonly string[] = Object.freeze([\n 'hover',\n 'press',\n 'active',\n 'focus',\n 'focus-visible',\n 'focus-within',\n 'disabled',\n])\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { GrammarConfigView } from "./candidate";
|
|
2
|
+
type Names = readonly string[] | ReadonlySet<string> | Readonly<Record<string, unknown>>;
|
|
3
|
+
type GrammarFontConfig = {
|
|
4
|
+
size?: Readonly<Record<string, unknown>>;
|
|
5
|
+
weight?: Readonly<Record<string, unknown>>;
|
|
6
|
+
lineHeight?: Readonly<Record<string, unknown>>;
|
|
7
|
+
letterSpacing?: Readonly<Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
export type GrammarSourceConfig = {
|
|
10
|
+
shorthands?: Readonly<Record<string, string>>;
|
|
11
|
+
media?: Names;
|
|
12
|
+
themes?: Readonly<Record<string, unknown>>;
|
|
13
|
+
tokensParsed?: Partial<Record<"space" | "size" | "radius" | "zIndex" | "color", Readonly<Record<string, unknown>>>>;
|
|
14
|
+
fontsParsed?: Readonly<Record<string, GrammarFontConfig | undefined>>;
|
|
15
|
+
};
|
|
16
|
+
export type CreateGrammarConfigViewOptions = {
|
|
17
|
+
platformNames?: Names;
|
|
18
|
+
/** overrides the derived container size set (the web adapter's resolved set) */
|
|
19
|
+
containerSizeNames?: readonly string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The one owner of "does this media query measure a size". A `hover` or
|
|
23
|
+
* `pointer` key measures nothing a container has, so it gets no `@` form.
|
|
24
|
+
* Accepts the query TEXT (`(min-width: 900px)`) or the config's media OBJECT
|
|
25
|
+
* (`{ minWidth: 900 }`) — both spellings of the same fact.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isContainerSizeQuery(query: unknown): boolean;
|
|
28
|
+
export declare const grammarPlatformNames: ReadonlySet<string>;
|
|
29
|
+
export declare const grammarPlatformGroups: ReadonlyMap<string, ReadonlySet<string>>;
|
|
30
|
+
/**
|
|
31
|
+
* Platform clause specificity, mirroring the runtime directStyle ranks: a TV
|
|
32
|
+
* variant beats its base platform, which beats `native`, independent of
|
|
33
|
+
* authored order. Non-platform modifiers never rank.
|
|
34
|
+
*/
|
|
35
|
+
export declare function grammarPlatformRank(modifier: string): number;
|
|
36
|
+
/**
|
|
37
|
+
* Creates the dependency-free config projection consumed by the shared style grammar.
|
|
38
|
+
* Runtime and compiler integrations must classify candidates through this same view so
|
|
39
|
+
* a candidate cannot be claimed by one side and emitted by the other.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createGrammarConfigView(config: GrammarSourceConfig, options?: CreateGrammarConfigViewOptions): GrammarConfigView;
|
|
42
|
+
export {};
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAAA,cAAc,yBAAyB;KAGlC,4BAA4B,sBAAsB,SAAS;KAE3D,oBAAoB;CACvB,OAAO,SAAS;CAChB,SAAS,SAAS;CAClB,aAAa,SAAS;CACtB,gBAAgB,SAAS;;AAG3B,YAAY,sBAAsB;CAChC,aAAa,SAAS;CACtB,QAAQ;CACR,SAAS,SAAS;CAClB,eAAe,QACb,OACE,UAAU,SAAS,WAAW,WAAW,SACzC,SAAS;CAGb,cAAc,SAAS,eAAe;;AAGxC,YAAY,iCAAiC;CAC3C,gBAAgB;;CAEhB;;;;;;;;AASF,OAAO,iBAAS,qBAAqB;AAiBrC,OAAO,cAAM,sBAAsB;AAUnC,OAAO,cAAM,uBAAuB,oBAAoB;;;;;;AAcxD,OAAO,iBAAS,oBAAoB;;;;;;AA0BpC,OAAO,iBAAS,wBACd,QAAQ,qBACR,UAAS,iCACR",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/config.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"import type { GrammarConfigView } from './candidate'\nimport type { TokenCategory } from './registry'\n\ntype Names = readonly string[] | ReadonlySet<string> | Readonly<Record<string, unknown>>\n\ntype GrammarFontConfig = {\n size?: Readonly<Record<string, unknown>>\n weight?: Readonly<Record<string, unknown>>\n lineHeight?: Readonly<Record<string, unknown>>\n letterSpacing?: Readonly<Record<string, unknown>>\n}\n\nexport type GrammarSourceConfig = {\n shorthands?: Readonly<Record<string, string>>\n media?: Names\n themes?: Readonly<Record<string, unknown>>\n tokensParsed?: Partial<\n Record<\n 'space' | 'size' | 'radius' | 'zIndex' | 'color',\n Readonly<Record<string, unknown>>\n >\n >\n fontsParsed?: Readonly<Record<string, GrammarFontConfig | undefined>>\n}\n\nexport type CreateGrammarConfigViewOptions = {\n platformNames?: Names\n /** overrides the derived container size set (the web adapter's resolved set) */\n containerSizeNames?: readonly string[]\n}\n\n/**\n * The one owner of \"does this media query measure a size\". A `hover` or\n * `pointer` key measures nothing a container has, so it gets no `@` form.\n * Accepts the query TEXT (`(min-width: 900px)`) or the config's media OBJECT\n * (`{ minWidth: 900 }`) — both spellings of the same fact.\n */\nexport function isContainerSizeQuery(query: unknown): boolean {\n if (typeof query === 'string') {\n return (\n query.includes('width') ||\n query.includes('height') ||\n query.includes('inline-size') ||\n query.includes('block-size')\n )\n }\n if (query && typeof query === 'object') {\n for (const key in query as Readonly<Record<string, unknown>>) {\n if (/width|height|size/i.test(key)) return true\n }\n }\n return false\n}\n\nexport const grammarPlatformNames: ReadonlySet<string> = new Set([\n 'web',\n 'native',\n 'android',\n 'ios',\n 'tv',\n 'androidtv',\n 'tvos',\n])\n\nexport const grammarPlatformGroups: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n ['native', new Set(['android', 'ios', 'androidtv', 'tvos'])],\n ['tv', new Set(['androidtv', 'tvos'])],\n // react-native-tvos reports Platform.OS 'android'/'ios' on TV devices, so the\n // base platform contains its TV variant (matches runtime platformMatches)\n ['android', new Set(['androidtv'])],\n ['ios', new Set(['tvos'])],\n])\n\n/**\n * Platform clause specificity, mirroring the runtime directStyle ranks: a TV\n * variant beats its base platform, which beats `native`, independent of\n * authored order. Non-platform modifiers never rank.\n */\nexport function grammarPlatformRank(modifier: string): number {\n return modifier === 'native' || modifier === 'web'\n ? 1\n : modifier === 'androidtv' || modifier === 'tvos'\n ? 3\n : 2\n}\n\nfunction addNames(target: Set<string>, source: Names | undefined): void {\n if (!source) return\n if (Array.isArray(source)) {\n for (const key of source) target.add(key)\n return\n }\n if (source instanceof Set) {\n for (const key of source) target.add(key)\n return\n }\n for (const key in source) target.add(key)\n}\n\n/**\n * Creates the dependency-free config projection consumed by the shared style grammar.\n * Runtime and compiler integrations must classify candidates through this same view so\n * a candidate cannot be claimed by one side and emitted by the other.\n */\nexport function createGrammarConfigView(\n config: GrammarSourceConfig,\n options: CreateGrammarConfigViewOptions = {}\n): GrammarConfigView {\n const tokenNames: Record<TokenCategory, Set<string>> = {\n space: new Set(),\n size: new Set(),\n radius: new Set(),\n zIndex: new Set(),\n color: new Set(),\n fontFamily: new Set(),\n fontSize: new Set(),\n fontWeight: new Set(),\n lineHeight: new Set(),\n letterSpacing: new Set(),\n }\n\n for (const category of ['space', 'size', 'radius', 'zIndex', 'color'] as const) {\n addNames(tokenNames[category], config.tokensParsed?.[category])\n }\n\n for (const themeName in config.themes) {\n const theme = config.themes[themeName]\n if (theme && typeof theme === 'object' && !Array.isArray(theme)) {\n addNames(tokenNames.color, theme as Readonly<Record<string, unknown>>)\n }\n }\n\n for (const familyName in config.fontsParsed) {\n tokenNames.fontFamily.add(familyName)\n const font = config.fontsParsed[familyName]\n addNames(tokenNames.fontSize, font?.size)\n addNames(tokenNames.fontWeight, font?.weight)\n addNames(tokenNames.lineHeight, font?.lineHeight)\n addNames(tokenNames.letterSpacing, font?.letterSpacing)\n }\n\n // container size derivation needs query information, which only the\n // record form of `media` carries (values are media objects or query text).\n // a bare name list stays undefined = unknown, and the modifier registry\n // refuses container claims for it rather than guessing\n let containerSizeNames = options.containerSizeNames\n if (\n containerSizeNames === undefined &&\n config.media &&\n !Array.isArray(config.media) &&\n !(config.media instanceof Set)\n ) {\n const derived: string[] = []\n const media = config.media as Readonly<Record<string, unknown>>\n for (const key in media) {\n if (isContainerSizeQuery(media[key])) derived.push(key)\n }\n containerSizeNames = derived\n }\n\n return {\n shorthands: config.shorthands,\n mediaNames: config.media,\n themeNames: config.themes,\n platformNames: options.platformNames ?? grammarPlatformNames,\n tokenNames,\n containerSizeNames,\n }\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ClausePrecedenceOrder } from "./clausePrecedence";
|
|
2
|
+
import type { ModifierRegistryView, ParsedValue } from "./valueTypes";
|
|
3
|
+
export interface ActiveConditions {
|
|
4
|
+
states: ReadonlySet<string>;
|
|
5
|
+
themes: ReadonlySet<string>;
|
|
6
|
+
media: ReadonlySet<string>;
|
|
7
|
+
/** config declaration order; falls back to `media` insertion order in tests */
|
|
8
|
+
mediaOrder?: ClausePrecedenceOrder;
|
|
9
|
+
platform: string;
|
|
10
|
+
groups: (modifier: string) => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* whether a container query modifier (`@sm`, `@sm/card`) currently holds.
|
|
13
|
+
* Like groups, this is a callback because the answer lives with the component
|
|
14
|
+
* tree: resolving it needs the measured size of the nearest or named
|
|
15
|
+
* container, whose measurement timing is its own design item.
|
|
16
|
+
*/
|
|
17
|
+
containers: (modifier: string) => boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a program to one payload using the shared fixed precedence key.
|
|
21
|
+
* Authored order only breaks exact-key ties, so a later restatement of the
|
|
22
|
+
* same normalized condition set wins while distinct condition sets are stable
|
|
23
|
+
* under reordering.
|
|
24
|
+
*/
|
|
25
|
+
export declare function evaluateProgram(value: ParsedValue, registry: ModifierRegistryView, active: ActiveConditions): string | null;
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=evaluateProgram.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AACA,cAMO,6BACA;AACP,cAA4B,sBAAsB,mBAAmB;AAErE,iBAAiB,iBAAiB;CAChC,QAAQ;CACR,QAAQ;CACR,OAAO;;CAEP,aAAa;CACb;CACA,SAAS;;;;;;;CAOT,aAAa;;;;;;;;AASf,OAAO,iBAAS,gBACd,OAAO,aACP,UAAU,sBACV,QAAQ",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/evaluateProgram.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"import { grammarPlatformGroups } from './config'\nimport {\n canonicalClauseModifier,\n compareClausePrecedence,\n createClausePrecedenceOrder,\n getClausePrecedenceKeyFromKinds,\n type ClausePrecedenceKey,\n type ClausePrecedenceOrder,\n} from './clausePrecedence'\nimport type { ModifierKind, ModifierRegistryView, ParsedValue } from './valueTypes'\n\nexport interface ActiveConditions {\n states: ReadonlySet<string>\n themes: ReadonlySet<string>\n media: ReadonlySet<string>\n /** config declaration order; falls back to `media` insertion order in tests */\n mediaOrder?: ClausePrecedenceOrder\n platform: string\n groups: (modifier: string) => boolean\n /**\n * whether a container query modifier (`@sm`, `@sm/card`) currently holds.\n * Like groups, this is a callback because the answer lives with the component\n * tree: resolving it needs the measured size of the nearest or named\n * container, whose measurement timing is its own design item.\n */\n containers: (modifier: string) => boolean\n}\n\n/**\n * Resolves a program to one payload using the shared fixed precedence key.\n * Authored order only breaks exact-key ties, so a later restatement of the\n * same normalized condition set wins while distinct condition sets are stable\n * under reordering.\n */\nexport function evaluateProgram(\n value: ParsedValue,\n registry: ModifierRegistryView,\n active: ActiveConditions\n): string | null {\n let payload: string | null = null\n let found = false\n let best: ClausePrecedenceKey | undefined\n const order = active.mediaOrder ?? createClausePrecedenceOrder(active.media)\n\n for (let clauseIndex = 0; clauseIndex < value.clauses.length; clauseIndex++) {\n const clause = value.clauses[clauseIndex]\n let matches = true\n const kinds: (ModifierKind | undefined)[] = []\n\n for (\n let modifierIndex = 0;\n modifierIndex < clause.modifiers.length;\n modifierIndex++\n ) {\n const modifier = canonicalClauseModifier(clause.modifiers[modifierIndex])\n const kind = registry.get(modifier)\n kinds.push(kind)\n\n if (kind === 'state') {\n matches = active.states.has(modifier)\n } else if (kind === 'theme') {\n matches = active.themes.has(modifier)\n } else if (kind === 'media') {\n matches = active.media.has(modifier)\n } else if (kind === 'platform') {\n matches =\n modifier === active.platform ||\n (grammarPlatformGroups.get(modifier)?.has(active.platform) ?? false)\n } else if (kind === 'group') {\n matches = active.groups(modifier)\n } else if (kind === 'container') {\n matches = active.containers(modifier)\n } else {\n matches = false\n }\n\n if (!matches) break\n }\n\n if (!matches) continue\n\n const precedence = getClausePrecedenceKeyFromKinds(clause.modifiers, kinds, order)\n if (best && compareClausePrecedence(precedence, best) < 0) continue\n\n payload = clause.payload\n best = precedence\n found = true\n }\n\n return found ? payload : value.base\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ParsedValue } from "./valueTypes";
|
|
2
|
+
interface FontShorthandTargets {
|
|
3
|
+
style: readonly string[];
|
|
4
|
+
weight: readonly string[];
|
|
5
|
+
size: readonly string[];
|
|
6
|
+
lineHeight: readonly string[];
|
|
7
|
+
family: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
/** authored prop -> the true longhands each component kind lands on */
|
|
10
|
+
export declare const fontShorthandTargets: Readonly<Record<string, FontShorthandTargets>>;
|
|
11
|
+
export interface FontShorthandError {
|
|
12
|
+
code: "unsupported-font-component";
|
|
13
|
+
component: string;
|
|
14
|
+
where: "base" | number;
|
|
15
|
+
}
|
|
16
|
+
export declare function splitFontValue(value: ParsedValue): {
|
|
17
|
+
entries: Array<{
|
|
18
|
+
property: string;
|
|
19
|
+
value: ParsedValue;
|
|
20
|
+
}>;
|
|
21
|
+
errors: FontShorthandError[];
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=fontShorthand.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAYA,cAA4B,mBAAmB;UAErC,qBAAqB;CAC7B;CACA;CACA;CACA;CACA;;;AAIF,OAAO,cAAM,sBAAsB,SAAS,eAAe;AAqC3D,iBAAiB,mBAAmB;CAClC,MAAM;CACN;CACA,OAAO;;AAWT,OAAO,iBAAS,eAAe,OAAO,cAAc;CAClD,SAAS,MAAM;EAAE;EAAkB,OAAO;;CAC1C,QAAQ",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/fontShorthand.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"// The font shorthand: value-dependent splitting of the resetting CSS `font`\n// shorthand into per-longhand programs, completing the family model. The\n// micro-syntax is positional — optional style/weight components, then the\n// size (optionally `size/line-height`), then the family tail, which is joined\n// verbatim so comma lists and quoted names survive.\n//\n// Conservative by design: ambiguous or unsupported components (`normal`,\n// `small-caps`, stretch keywords, system font keywords, size keywords) error\n// so the whole value stays on the legacy path rather than converting into a\n// subtly different meaning.\n\nimport { splitTopLevelComponents } from './backgroundFamily'\nimport type { ParsedClause, ParsedValue } from './valueTypes'\n\ninterface FontShorthandTargets {\n style: readonly string[]\n weight: readonly string[]\n size: readonly string[]\n lineHeight: readonly string[]\n family: readonly string[]\n}\n\n/** authored prop -> the true longhands each component kind lands on */\nexport const fontShorthandTargets: Readonly<Record<string, FontShorthandTargets>> = {\n font: {\n style: ['fontStyle'],\n weight: ['fontWeight'],\n size: ['fontSize'],\n lineHeight: ['lineHeight'],\n family: ['fontFamily'],\n },\n}\n\nconst styleKeywords = new Set(['italic', 'oblique'])\nconst weightKeywords = new Set(['bold', 'bolder', 'lighter'])\n// `normal` is ambiguous (style, variant, or weight), and these have no\n// cross-platform longhand contribution\nconst unsupportedKeywords = new Set([\n 'normal',\n 'small-caps',\n 'ultra-condensed',\n 'extra-condensed',\n 'condensed',\n 'semi-condensed',\n 'semi-expanded',\n 'expanded',\n 'extra-expanded',\n 'ultra-expanded',\n // system font keywords have no longhand equivalent at all\n 'caption',\n 'icon',\n 'menu',\n 'message-box',\n 'small-caption',\n 'status-bar',\n])\n\nconst sizePattern = /^-?(\\d+\\.?\\d*|\\.\\d+)(?:[a-z%]+)?$/i\nconst weightNumberPattern = /^[1-9]00$/\n\nexport interface FontShorthandError {\n code: 'unsupported-font-component'\n component: string\n where: 'base' | number\n}\n\ntype FontKind = keyof FontShorthandTargets\n\ninterface MutableProgram {\n base: string | null\n clauses: ParsedClause[]\n present: boolean\n}\n\nexport function splitFontValue(value: ParsedValue): {\n entries: Array<{ property: string; value: ParsedValue }>\n errors: FontShorthandError[]\n} {\n const targets = fontShorthandTargets.font\n const errors: FontShorthandError[] = []\n const kinds: readonly FontKind[] = ['style', 'weight', 'size', 'lineHeight', 'family']\n const programs: Record<FontKind, MutableProgram> = {\n style: { base: null, clauses: [], present: false },\n weight: { base: null, clauses: [], present: false },\n size: { base: null, clauses: [], present: false },\n lineHeight: { base: null, clauses: [], present: false },\n family: { base: null, clauses: [], present: false },\n }\n\n for (let clauseIndex = -1; clauseIndex < value.clauses.length; clauseIndex++) {\n const isBase = clauseIndex === -1\n const payload = isBase ? value.base : value.clauses[clauseIndex].payload\n if (payload === null) continue\n const where = isBase ? ('base' as const) : clauseIndex\n\n const components = splitTopLevelComponents(payload)\n const found: Partial<Record<FontKind, string>> = {}\n let sizeIndex = -1\n\n for (let index = 0; index < components.length; index++) {\n const component = components[index]\n const lower = component.toLowerCase()\n if (unsupportedKeywords.has(lower)) {\n errors.push({ code: 'unsupported-font-component', component, where })\n continue\n }\n if (styleKeywords.has(lower)) {\n if (found.style !== undefined) {\n errors.push({ code: 'unsupported-font-component', component, where })\n continue\n }\n found.style = component\n continue\n }\n if (weightKeywords.has(lower) || weightNumberPattern.test(component)) {\n if (found.weight !== undefined) {\n errors.push({ code: 'unsupported-font-component', component, where })\n continue\n }\n found.weight = component\n continue\n }\n const slash = component.indexOf('/')\n const sizePart = slash === -1 ? component : component.slice(0, slash)\n if (sizePattern.test(sizePart)) {\n if (found.size !== undefined) {\n errors.push({ code: 'unsupported-font-component', component, where })\n continue\n }\n found.size = sizePart\n if (slash !== -1) found.lineHeight = component.slice(slash + 1)\n sizeIndex = index\n // everything after the size is the family, joined verbatim\n const family = components.slice(index + 1).join(' ')\n if (family) found.family = family\n break\n }\n // a component before the size that nothing classified\n errors.push({ code: 'unsupported-font-component', component, where })\n }\n\n if (sizeIndex === -1) {\n errors.push({\n code: 'unsupported-font-component',\n component: payload,\n where,\n })\n }\n\n for (const kind of kinds) {\n const component = found[kind]\n if (component === undefined) continue\n const program = programs[kind]\n program.present = true\n if (isBase) {\n program.base = component\n } else {\n program.clauses.push({\n modifiers: value.clauses[clauseIndex].modifiers,\n payload: component,\n })\n }\n }\n }\n\n const entries: Array<{ property: string; value: ParsedValue }> = []\n for (const kind of kinds) {\n const program = programs[kind]\n if (!program.present) continue\n const shared: ParsedValue = { base: program.base, clauses: program.clauses }\n for (const longhand of targets[kind]) {\n entries.push({ property: longhand, value: shared })\n }\n }\n\n return { entries, errors }\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ParsedValue } from "./valueTypes";
|
|
2
|
+
export interface GeometricShorthandError {
|
|
3
|
+
code: "unsupported-geometric-payload";
|
|
4
|
+
payload: string;
|
|
5
|
+
where: "base" | number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Splits a geometric shorthand's parsed program into per-longhand programs by
|
|
9
|
+
* slot. Returns null when `prop` is not a geometric shorthand, or when every
|
|
10
|
+
* payload is single-component (nothing to distribute — the caller's ordinary
|
|
11
|
+
* expansion handles that identically and cheaper).
|
|
12
|
+
*/
|
|
13
|
+
export declare function splitGeometricShorthandValue(prop: string, value: ParsedValue): {
|
|
14
|
+
entries: Array<{
|
|
15
|
+
property: string;
|
|
16
|
+
value: ParsedValue;
|
|
17
|
+
}>;
|
|
18
|
+
errors: GeometricShorthandError[];
|
|
19
|
+
} | null;
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=geometricShorthand.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAeA,cAA4B,mBAAmB;AAS/C,iBAAiB,wBAAwB;CACvC,MAAM;CACN;CACA,OAAO;;;;;;;;AAST,OAAO,iBAAS,6BACd,cACA,OAAO,cACN;CACD,SAAS,MAAM;EAAE;EAAkB,OAAO;;CAC1C,QAAQ",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/geometricShorthand.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"// Geometric shorthand slot semantics for program values (design record,\n// \"Bare numbers resolve config-first ... and per component value:\n// `p=\"4 8\"` resolves both\"). A multi-component payload on a geometric\n// shorthand distributes by the CSS slot pattern — sides alternate for two\n// values, three values mirror the second, four map directly — producing one\n// SINGLE-component program per longhand. Without this, every side received\n// the whole multi-value payload and the browser dropped the declaration\n// silently.\n//\n// Function values and slash syntax (`borderRadius=\"8px / 4px\"`) do not\n// distribute faithfully and return an error, which keeps the value on the\n// single-program path where the payload-shape diagnostic reports it.\n\nimport { splitTopLevelComponents } from './backgroundFamily'\nimport { longhandExpansionTable } from './programs'\nimport type { ParsedClause, ParsedValue } from './valueTypes'\n\n// identical index patterns for box sides (T/R/B/L) and radius corners\n// (TL/TR/BR/BL); two-slot pairs (horizontal/vertical, gap) take one or two\nconst slotPatterns: Record<number, Record<number, readonly number[]>> = {\n 4: { 1: [0, 0, 0, 0], 2: [0, 1, 0, 1], 3: [0, 1, 2, 1], 4: [0, 1, 2, 3] },\n 2: { 1: [0, 0], 2: [0, 1] },\n}\n\nexport interface GeometricShorthandError {\n code: 'unsupported-geometric-payload'\n payload: string\n where: 'base' | number\n}\n\n/**\n * Splits a geometric shorthand's parsed program into per-longhand programs by\n * slot. Returns null when `prop` is not a geometric shorthand, or when every\n * payload is single-component (nothing to distribute — the caller's ordinary\n * expansion handles that identically and cheaper).\n */\nexport function splitGeometricShorthandValue(\n prop: string,\n value: ParsedValue\n): {\n entries: Array<{ property: string; value: ParsedValue }>\n errors: GeometricShorthandError[]\n} | null {\n const longhands = longhandExpansionTable[prop]\n if (!longhands) return null\n const patterns = slotPatterns[longhands.length]\n if (!patterns) return null\n\n // fast path: nothing multi-component, nothing to do\n let hasMulti = false\n const payloadComponents: string[][] = []\n for (let index = -1; index < value.clauses.length; index++) {\n const payload = index === -1 ? value.base : value.clauses[index].payload\n if (payload === null) {\n payloadComponents.push([])\n continue\n }\n if (payload.includes('/')) return null\n const components = splitTopLevelComponents(payload)\n payloadComponents.push(components)\n if (components.length > 1) hasMulti = true\n }\n if (!hasMulti) return null\n\n const errors: GeometricShorthandError[] = []\n // per longhand: pick this slot's component from every payload\n const perLonghand: Array<{ base: string | null; clauses: ParsedClause[] }> =\n longhands.map(() => ({ base: null, clauses: [] }))\n\n for (let index = -1; index < value.clauses.length; index++) {\n const payload = index === -1 ? value.base : value.clauses[index].payload\n if (payload === null) continue\n const components = payloadComponents[index + 1]\n const pattern = patterns[components.length]\n if (!pattern) {\n errors.push({\n code: 'unsupported-geometric-payload',\n payload,\n where: index === -1 ? 'base' : index,\n })\n continue\n }\n for (let slot = 0; slot < longhands.length; slot++) {\n const component = components[pattern[slot]]\n if (index === -1) {\n perLonghand[slot].base = component\n } else {\n perLonghand[slot].clauses.push({\n modifiers: value.clauses[index].modifiers,\n payload: component,\n })\n }\n }\n }\n\n if (errors.length) return { entries: [], errors }\n\n return {\n entries: longhands.map((longhand, slot) => ({\n property: longhand,\n value: { base: perLonghand[slot].base, clauses: perLonghand[slot].clauses },\n })),\n errors,\n }\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type ClausePrecedenceOrder } from "./clausePrecedence";
|
|
2
|
+
import type { LonghandProgram, ModifierRegistryView } from "./valueTypes";
|
|
3
|
+
/**
|
|
4
|
+
* Where a condition's selector fragment is matched, relative to the subject: on
|
|
5
|
+
* the subject itself, strictly above it, or either.
|
|
6
|
+
*/
|
|
7
|
+
export type ConditionScope = "self" | "within" | "is-or-within";
|
|
8
|
+
export interface ConditionSelector {
|
|
9
|
+
/** compound selector piece, eg `:hover`, `.t_dark`, `[aria-disabled]` */
|
|
10
|
+
fragment: string;
|
|
11
|
+
/** defaults to `self` */
|
|
12
|
+
scope?: ConditionScope;
|
|
13
|
+
/**
|
|
14
|
+
* capability guard the rule must nest in, eg `(hover: hover)` so touch
|
|
15
|
+
* devices never sticky-trigger hover styles
|
|
16
|
+
*/
|
|
17
|
+
media?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Interaction-state selector spellings: `disabled` is an attribute rather than
|
|
21
|
+
* `:disabled`, and enter matches the unmounted class on the subject or above it.
|
|
22
|
+
* Mirrored as data instead of imported because this package must not depend on
|
|
23
|
+
* @tamagui/web.
|
|
24
|
+
*
|
|
25
|
+
* Lifecycle clauses use classes supplied by createComponent. `is-or-within`
|
|
26
|
+
* lets a presence boundary carry the lifecycle state for descendants too.
|
|
27
|
+
*/
|
|
28
|
+
export declare const defaultStateSelectors: Readonly<Record<string, ConditionSelector>>;
|
|
29
|
+
export interface LowerProgramOptions {
|
|
30
|
+
/** classifies each modifier; the same registry the value was parsed against */
|
|
31
|
+
registry: ModifierRegistryView;
|
|
32
|
+
/** opaque stamp for the resolved config that produced these payloads */
|
|
33
|
+
configRevision: string;
|
|
34
|
+
/** media key -> the `@media` condition text, eg `(max-width: 860px)` */
|
|
35
|
+
mediaQueries?: Readonly<Record<string, string>>;
|
|
36
|
+
/**
|
|
37
|
+
* media key -> the `@container` condition text, eg `(min-width: 24rem)`. Sizes
|
|
38
|
+
* are the same keys as `mediaQueries`, but the query text differs: container
|
|
39
|
+
* queries measure the container, not the viewport, so the caller derives both
|
|
40
|
+
* from config.
|
|
41
|
+
*/
|
|
42
|
+
containerQueries?: Readonly<Record<string, string>>;
|
|
43
|
+
/** modifier -> selector, defaults to `defaultStateSelectors` */
|
|
44
|
+
stateSelectors?: Readonly<Record<string, ConditionSelector>>;
|
|
45
|
+
/** precomputed media declaration order; derived from mediaQueries by default */
|
|
46
|
+
precedenceOrder?: ClausePrecedenceOrder;
|
|
47
|
+
/** theme class prefix; `t_` gives `.t_dark` */
|
|
48
|
+
themeClassPrefix?: string;
|
|
49
|
+
/** group class prefix; `t_group_` gives `.t_group_card` */
|
|
50
|
+
groupClassPrefix?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface LoweredProgram {
|
|
53
|
+
className: string;
|
|
54
|
+
/** base rule first, then one rule per emitted clause in precedence order */
|
|
55
|
+
rules: string[];
|
|
56
|
+
/**
|
|
57
|
+
* Present when the program writes a per-axis custom property (`x`, `y`,
|
|
58
|
+
* `scaleX`, `scaleY`). The composing rule turns the axis variables into the
|
|
59
|
+
* real CSS property and is identical for every element using that axis group,
|
|
60
|
+
* so it carries its own class name and hash: the caller adds this class too and
|
|
61
|
+
* insertion dedups it to one rule per sheet. Its specificity is the same
|
|
62
|
+
* (0,1,0) as every other rule here.
|
|
63
|
+
*/
|
|
64
|
+
composition?: {
|
|
65
|
+
/** the CSS property being composed, and the classNames key to store it under */
|
|
66
|
+
property: string;
|
|
67
|
+
className: string;
|
|
68
|
+
rules: string[];
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export declare function lowerProgram(program: LonghandProgram, options: LowerProgramOptions): LoweredProgram;
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=lowerProgram.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAyBA,cAOO,6BACA;AAIP,cAAc,iBAAiB,4BAA4B;;;;;AAM3D,YAAY,iBAAiB,SAAS,WAAW;AAEjD,iBAAiB,kBAAkB;;CAEjC;;CAEA,QAAQ;;;;;CAKR;;;;;;;;;;;AAYF,OAAO,cAAM,uBAAuB,SAAS,eAAe;AAoC5D,iBAAiB,oBAAoB;;CAEnC,UAAU;;CAEV;;CAEA,eAAe,SAAS;;;;;;;CAOxB,mBAAmB,SAAS;;CAE5B,iBAAiB,SAAS,eAAe;;CAEzC,kBAAkB;;CAElB;;CAEA;;AAGF,iBAAiB,eAAe;CAC9B;;CAEA;;;;;;;;;CASA,cAAc;;EAEZ;EACA;EACA;;;AA6CJ,OAAO,iBAAS,aACd,SAAS,iBACT,SAAS,sBACR",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/lowerProgram.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"// Web lowering: one program becomes one contiguous block of CSS rules.\n//\n// See plans/dom-tailwind-flat-values.md — \"The program block encoding\". The\n// invariants this file exists to hold:\n//\n// - every condition anchors on the subject class, Tailwind-group style, so a\n// clause is exactly ONE selector: conditions chain as `:where()` on the\n// subject in authored modifier order. Ancestor-scoped conditions become a\n// descendant test inside their own `:where()` (`.t_dark *`), which makes each\n// one independent, so nesting order between them never matters and no\n// ancestor-permutation selectors exist;\n// - rule order is ascending clause precedence; selector specificity encodes\n// depth, while platform clauses receive a floor above the maximum\n// non-platform depth. Self states contribute naturally; media/container\n// wrappers and :where()-scoped theme/group ancestors contribute zero;\n// - the block is inserted contiguously, so cross-program order never matters and\n// append-at-end is always safe.\n//\n// Payloads are emitted verbatim. Token resolution, opacity composition, and\n// value validation all happen upstream: this layer receives CSS-ready payloads,\n// and the same resolved program is what the class name hashes, so a program has\n// exactly one identity. Rule injection through a payload is structurally\n// impossible because the parser rejects a top-level `{`, `}`, or `;`.\n\nimport { parseContainerModifier, parseGroupModifier } from './modifierRegistry'\nimport {\n canonicalClauseModifier,\n clauseConditionSetKey,\n clauseSubjectClassRepetitions,\n compareClausePrecedence,\n createClausePrecedenceOrder,\n getClausePrecedenceKey,\n type ClausePrecedenceOrder,\n} from './clausePrecedence'\nimport { transformAxisCompositions } from './transformFamily'\nimport { programClassName } from './programHash'\nimport { stateToSelector } from './states'\nimport type { LonghandProgram, ModifierRegistryView } from './valueTypes'\n\n/**\n * Where a condition's selector fragment is matched, relative to the subject: on\n * the subject itself, strictly above it, or either.\n */\nexport type ConditionScope = 'self' | 'within' | 'is-or-within'\n\nexport interface ConditionSelector {\n /** compound selector piece, eg `:hover`, `.t_dark`, `[aria-disabled]` */\n fragment: string\n /** defaults to `self` */\n scope?: ConditionScope\n /**\n * capability guard the rule must nest in, eg `(hover: hover)` so touch\n * devices never sticky-trigger hover styles\n */\n media?: string\n}\n\n/**\n * Interaction-state selector spellings: `disabled` is an attribute rather than\n * `:disabled`, and enter matches the unmounted class on the subject or above it.\n * Mirrored as data instead of imported because this package must not depend on\n * @tamagui/web.\n *\n * Lifecycle clauses use classes supplied by createComponent. `is-or-within`\n * lets a presence boundary carry the lifecycle state for descendants too.\n */\nexport const defaultStateSelectors: Readonly<Record<string, ConditionSelector>> =\n Object.freeze({\n hover: { fragment: ':hover', media: '(hover: hover)' },\n // the press modifier's CSS pseudo name is `active`\n press: { fragment: ':active' },\n // the registered alias of press\n active: { fragment: ':active' },\n focus: { fragment: ':focus' },\n 'focus-visible': { fragment: ':focus-visible' },\n 'focus-within': { fragment: ':focus-within' },\n disabled: { fragment: '[aria-disabled]' },\n enter: { fragment: '.t_unmounted', scope: 'is-or-within' },\n exit: { fragment: '.t_exiting', scope: 'is-or-within' },\n // component-tier states, from the shared state vocabulary's web selectors\n ...(Object.fromEntries(\n Object.entries(stateToSelector).map(([state, selector]) => [\n state,\n { fragment: selector },\n ])\n ) as Record<string, ConditionSelector>),\n })\n\n// core writes the unnamed group's class as `t_group_true`, from the boolean\n// `group` prop (see getSplitStyles' group class name construction)\nconst unnamedGroup = 'true'\n\n// a capability guard (hover: hover) wraps once even when the subject and a\n// group both carry the hover state in one clause\nfunction pushCapabilityGuard(wrappers: string[], media: string): void {\n const guard = `@media ${media}`\n for (let index = 0; index < wrappers.length; index++) {\n if (wrappers[index] === guard) return\n }\n wrappers.push(guard)\n}\n\nexport interface LowerProgramOptions {\n /** classifies each modifier; the same registry the value was parsed against */\n registry: ModifierRegistryView\n /** opaque stamp for the resolved config that produced these payloads */\n configRevision: string\n /** media key -> the `@media` condition text, eg `(max-width: 860px)` */\n mediaQueries?: Readonly<Record<string, string>>\n /**\n * media key -> the `@container` condition text, eg `(min-width: 24rem)`. Sizes\n * are the same keys as `mediaQueries`, but the query text differs: container\n * queries measure the container, not the viewport, so the caller derives both\n * from config.\n */\n containerQueries?: Readonly<Record<string, string>>\n /** modifier -> selector, defaults to `defaultStateSelectors` */\n stateSelectors?: Readonly<Record<string, ConditionSelector>>\n /** precomputed media declaration order; derived from mediaQueries by default */\n precedenceOrder?: ClausePrecedenceOrder\n /** theme class prefix; `t_` gives `.t_dark` */\n themeClassPrefix?: string\n /** group class prefix; `t_group_` gives `.t_group_card` */\n groupClassPrefix?: string\n}\n\nexport interface LoweredProgram {\n className: string\n /** base rule first, then one rule per emitted clause in precedence order */\n rules: string[]\n /**\n * Present when the program writes a per-axis custom property (`x`, `y`,\n * `scaleX`, `scaleY`). The composing rule turns the axis variables into the\n * real CSS property and is identical for every element using that axis group,\n * so it carries its own class name and hash: the caller adds this class too and\n * insertion dedups it to one rule per sheet. Its specificity is the same\n * (0,1,0) as every other rule here.\n */\n composition?: {\n /** the CSS property being composed, and the classNames key to store it under */\n property: string\n className: string\n rules: string[]\n }\n}\n\nfunction hyphenate(property: string): string {\n let out = ''\n for (let index = 0; index < property.length; index++) {\n const code = property.charCodeAt(index)\n out +=\n code >= 65 && code <= 90 ? `-${property[index].toLowerCase()}` : property[index]\n }\n return out\n}\n\nfunction conditionSelector(\n fragment: string,\n scope: ConditionScope,\n zeroSpecificity: boolean\n): string {\n const pseudo = zeroSpecificity ? 'where' : 'is'\n if (scope === 'within') return `:${pseudo}(${fragment} *)`\n if (scope === 'is-or-within') {\n return `:${pseudo}(${fragment}, ${fragment} *)`\n }\n return zeroSpecificity ? `:where(${fragment})` : fragment\n}\n\ntype PointerEventsMode = 'auto' | 'none' | 'box-none' | 'box-only'\n\nfunction isPointerEventsMode(value: string): value is PointerEventsMode {\n return (\n value === 'auto' || value === 'none' || value === 'box-none' || value === 'box-only'\n )\n}\n\nfunction pointerEventsCSS(mode: PointerEventsMode): {\n subject: 'auto' | 'none'\n children: 'auto' | 'none'\n} {\n return {\n subject: mode === 'none' || mode === 'box-none' ? 'none' : 'auto',\n children: mode === 'none' || mode === 'box-only' ? 'none' : 'auto',\n }\n}\n\nexport function lowerProgram(\n program: LonghandProgram,\n options: LowerProgramOptions\n): LoweredProgram {\n const {\n registry,\n configRevision,\n mediaQueries,\n containerQueries,\n stateSelectors = defaultStateSelectors,\n precedenceOrder = createClausePrecedenceOrder(mediaQueries),\n themeClassPrefix = 't_',\n groupClassPrefix = 't_group_',\n } = options\n\n const className = programClassName(program.property, program.value, configRevision)\n const declaration = hyphenate(program.property)\n const rules: string[] = []\n\n // React Native's box-only/box-none values need a subject rule and a direct-child\n // rule. If either appears in a program, every clause emits both halves so moving\n // between (for example) box-none and none cannot leave the base child rule active.\n const pointerEventsProgram =\n program.property === 'pointerEvents' &&\n [program.value.base, ...program.value.clauses.map((clause) => clause.payload)].some(\n (value) => value === 'box-none' || value === 'box-only'\n )\n\n const pushRule = (selector: string, wrappers: readonly string[], value: string) => {\n if (pointerEventsProgram && isPointerEventsMode(value)) {\n const pointerEvents = pointerEventsCSS(value)\n rules.push(\n wrapAtRules(`${selector}{${declaration}:${pointerEvents.subject}}`, wrappers)\n )\n rules.push(\n wrapAtRules(`${selector}>*{${declaration}:${pointerEvents.children}}`, wrappers)\n )\n return\n }\n rules.push(wrapAtRules(`${selector}{${declaration}:${value}}`, wrappers))\n }\n\n if (program.value.base !== null) {\n pushRule(`.${className}`, [], program.value.base)\n }\n\n const clauseSlots = new Map<\n string,\n { clause: (typeof program.value.clauses)[number]; index: number }\n >()\n for (let index = 0; index < program.value.clauses.length; index++) {\n const clause = program.value.clauses[index]\n clauseSlots.set(clauseConditionSetKey(clause.modifiers), { clause, index })\n }\n const clauses = [...clauseSlots.values()]\n .map((entry) => ({\n ...entry,\n precedence: getClausePrecedenceKey(\n entry.clause.modifiers,\n registry,\n precedenceOrder\n ),\n }))\n .sort(\n (left, right) =>\n compareClausePrecedence(left.precedence, right.precedence) ||\n left.index - right.index\n )\n\n for (const { clause, precedence } of clauses) {\n let selectorSuffix = ''\n let selfStateSpecificity = 0\n // at-rule preludes wrapping this clause, outermost first in authored order\n const wrappers: string[] = []\n let skip = false\n const seenModifiers = new Set<string>()\n\n for (const authoredModifier of clause.modifiers) {\n const modifier = canonicalClauseModifier(authoredModifier)\n if (seenModifiers.has(modifier)) continue\n seenModifiers.add(modifier)\n const kind = registry.get(modifier)\n\n if (kind === 'platform') {\n // a web clause applies here exactly as if unconditional at its position;\n // every other platform's clause belongs to native and is not web CSS\n if (modifier !== 'web') skip = true\n continue\n }\n\n if (kind === 'media') {\n const query = mediaQueries?.[modifier]\n if (!query) {\n throw new Error(\n `cannot lower \"${modifier}:\" — no media query was provided for media key \"${modifier}\"`\n )\n }\n wrappers.push(`@media ${query}`)\n continue\n }\n\n if (kind === 'container') {\n const container = parseContainerModifier(modifier)!\n const query = containerQueries?.[container.size]\n if (!query) {\n throw new Error(\n `cannot lower \"${modifier}:\" — no container query was provided for size \"${container.size}\"`\n )\n }\n wrappers.push(\n container.container === null\n ? `@container ${query}`\n : `@container ${container.container} ${query}`\n )\n continue\n }\n\n if (kind === 'state') {\n const state = stateSelectors[modifier]\n if (!state) {\n throw new Error(\n `cannot lower \"${modifier}:\" — the state has no web selector, so it cannot become CSS`\n )\n }\n selectorSuffix += conditionSelector(state.fragment, state.scope ?? 'self', false)\n selfStateSpecificity++\n if (state.media) pushCapabilityGuard(wrappers, state.media)\n continue\n }\n\n if (kind === 'theme') {\n // the theme class is on the subject or anywhere above it\n selectorSuffix += conditionSelector(\n `.${themeClassPrefix}${modifier}`,\n 'is-or-within',\n true\n )\n continue\n }\n\n if (kind === 'group') {\n const group = parseGroupModifier(modifier)!\n const state = stateSelectors[group.state]\n if (!state) {\n throw new Error(\n `cannot lower \"${modifier}:\" — the group state \"${group.state}\" has no web selector`\n )\n }\n // a group is always a parent, never the subject itself\n selectorSuffix += conditionSelector(\n `.${groupClassPrefix}${group.group ?? unnamedGroup}${state.fragment}`,\n 'within',\n true\n )\n if (state.media) pushCapabilityGuard(wrappers, state.media)\n continue\n }\n\n throw new Error(\n `cannot lower \"${modifier}:\" — it is not a registered modifier, so the value was never validated`\n )\n }\n\n if (skip) continue\n\n const selector =\n `.${className}`.repeat(\n clauseSubjectClassRepetitions(precedence, selfStateSpecificity)\n ) + selectorSuffix\n pushRule(selector, wrappers, clause.payload)\n }\n\n const composition = transformAxisCompositions[program.property]\n if (!composition) return { className, rules }\n\n // one shared rule per axis group: same text, same hash, inserted once\n const compositionClassName = programClassName(\n composition.property,\n { base: composition.value, clauses: [] },\n configRevision\n )\n const localDefaults = Object.entries(composition.defaults)\n .map(([property, value]) => `${property}:${value}`)\n .join(';')\n return {\n className,\n rules,\n composition: {\n property: composition.property,\n className: compositionClassName,\n rules: [\n `:where(.${compositionClassName}){${localDefaults}}`,\n `.${compositionClassName}{${composition.property}:${composition.value}}`,\n ],\n },\n }\n}\n\n/**\n * Media and container conditions wrap outermost, first authored outermost, and\n * both share one list so a chain mixing them keeps authored order. Nesting is\n * AND for arbitrary query texts, where joining with ` and ` would break on query\n * lists and on `screen and (…)` forms. Specificity is unmoved either way.\n */\nfunction wrapAtRules(rule: string, wrappers: readonly string[]): string {\n let out = rule\n for (let index = wrappers.length - 1; index >= 0; index--) {\n out = `${wrappers[index]} {${out}}`\n }\n return out\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ParsedValue } from "./valueTypes";
|
|
2
|
+
/** Prints one parsed value without changing payloads, modifier order, or clause order. */
|
|
3
|
+
export declare function formatParsedValue(value: ParsedValue): string;
|
|
4
|
+
/**
|
|
5
|
+
* Combine two flat values for the same property, later winning.
|
|
6
|
+
*
|
|
7
|
+
* The merge unit is the clause, so a later `borderColor="green"` overrides the
|
|
8
|
+
* earlier base without erasing an earlier `press:transparent`. Style values
|
|
9
|
+
* that carry no clause take the cheap path and the later one simply wins,
|
|
10
|
+
* which is every ordinary prop.
|
|
11
|
+
*/
|
|
12
|
+
export declare function mergeFlatValues(earlier: unknown, later: unknown): unknown;
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=mergeFlatValues.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAEA,cAAoC,mBAAmB;;AAGvD,OAAO,iBAAS,kBAAkB,OAAO;;;;;;;;;AAyBzC,OAAO,iBAAS,gBAAgB,kBAAkB",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/mergeFlatValues.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"import { mergeProgramValues } from './programs'\nimport { parseValue } from './valueParser'\nimport type { ModifierRegistryView, ParsedValue } from './valueTypes'\n\n/** Prints one parsed value without changing payloads, modifier order, or clause order. */\nexport function formatParsedValue(value: ParsedValue): string {\n const parts: string[] = []\n if (value.base !== null) parts.push(value.base)\n for (const clause of value.clauses) {\n parts.push(`${clause.modifiers.join(':')}:${clause.payload}`)\n }\n return parts.join(' ')\n}\n\n// merging only needs the parser to split a base from its clauses, and the\n// parser consults the registry for exactly one thing: whether a modifier is\n// registered at all. Nothing about the split depends on which kind comes back.\n// An accepting view therefore parses identically to a configured one, and it\n// keeps values whose modifiers this site cannot resolve (for example, a\n// config's media keys) mergeable instead of quietly dropping their clauses.\nconst acceptAnyModifier: ModifierRegistryView = { get: () => 'state' }\n\n/**\n * Combine two flat values for the same property, later winning.\n *\n * The merge unit is the clause, so a later `borderColor=\"green\"` overrides the\n * earlier base without erasing an earlier `press:transparent`. Style values\n * that carry no clause take the cheap path and the later one simply wins,\n * which is every ordinary prop.\n */\nexport function mergeFlatValues(earlier: unknown, later: unknown): unknown {\n if (typeof earlier !== 'string' || typeof later !== 'string') return later\n // a clause needs a colon; skipping the parse here keeps ordinary props off\n // the grammar path entirely\n if (!earlier.includes(':') && !later.includes(':')) return later\n\n const earlierParsed = parseValue(earlier, acceptAnyModifier)\n if (!earlierParsed.ok) return later\n const laterParsed = parseValue(later, acceptAnyModifier)\n if (!laterParsed.ok) return later\n if (!earlierParsed.value.clauses.length && !laterParsed.value.clauses.length) {\n return later\n }\n\n return formatParsedValue(mergeProgramValues(earlierParsed.value, laterParsed.value))\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { GrammarConfigView } from "./candidate";
|
|
2
|
+
import { type ModifierRegistryView } from "./valueTypes";
|
|
3
|
+
type Names = readonly string[] | ReadonlySet<string> | Readonly<Record<string, unknown>>;
|
|
4
|
+
export interface ModifierRegistryResult {
|
|
5
|
+
registry: ModifierRegistryView;
|
|
6
|
+
/** one human-readable line per name collision, in registration order */
|
|
7
|
+
diagnostics: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface CreateModifierRegistryOptions {
|
|
10
|
+
/**
|
|
11
|
+
* The media keys that measure a size, so `@key` is a meaningful container
|
|
12
|
+
* query. A `hover` or `pointer` media key measures nothing a container has, and
|
|
13
|
+
* `@container (hover: none)` is valid syntax with no meaning, so those keys have
|
|
14
|
+
* no `@` form.
|
|
15
|
+
*
|
|
16
|
+
* Overrides the view's derived `containerSizeNames`. When NEITHER is
|
|
17
|
+
* supplied the sizes are unknown: no container modifier registers and a
|
|
18
|
+
* diagnostic says so — an unknowable set refuses rather than over-claims.
|
|
19
|
+
* A caller with genuinely no container concept passes `[]` explicitly.
|
|
20
|
+
*/
|
|
21
|
+
containerSizeNames?: Names;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Every built-in interaction/state modifier spelling: the modifiers of the core
|
|
25
|
+
* pseudo-style props, their aliases, and the component-tier state words the
|
|
26
|
+
* behavior packages expose through DOM attributes.
|
|
27
|
+
*/
|
|
28
|
+
export declare const stateModifierNames: readonly string[];
|
|
29
|
+
/**
|
|
30
|
+
* Theme conditions name a root theme. Nested themes still inherit from that
|
|
31
|
+
* root, so `dark:` applies within `dark_blue`, but `dark_blue:` is not a
|
|
32
|
+
* condition of its own.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isRootThemeName(name: string): boolean;
|
|
35
|
+
export interface GroupModifier {
|
|
36
|
+
/** the state the parent group must be in, always a built-in state modifier */
|
|
37
|
+
state: string;
|
|
38
|
+
/** the group name, or null for the nearest unnamed group */
|
|
39
|
+
group: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Canonical spelling used by slot identity, precedence, hashing, and matching. */
|
|
42
|
+
export declare function canonicalClauseModifier(name: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Parameterized group modifiers use Tailwind's spelling: `group-hover` for the
|
|
45
|
+
* nearest unnamed group and `group-hover/card` for a named one. The state part
|
|
46
|
+
* must be a built-in state modifier; the name part is an identifier. Returns
|
|
47
|
+
* null for anything else, which is what makes the spelling a single source of
|
|
48
|
+
* truth for both registration and lowering.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseGroupModifier(name: string): GroupModifier | null;
|
|
51
|
+
export interface ContainerModifier {
|
|
52
|
+
/** the size condition; the registry only accepts a registered media name here */
|
|
53
|
+
size: string;
|
|
54
|
+
/** the container name, or null for the nearest container */
|
|
55
|
+
container: string | null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Container query modifiers own the `@` prefix: `@sm` targets the nearest
|
|
59
|
+
* container and `@sm/card` a named one (plan decisions 17-18). Plain `sm:` stays
|
|
60
|
+
* a viewport media query, which is why the prefix is reserved.
|
|
61
|
+
*
|
|
62
|
+
* This parses the spelling only. Whether `size` names a registered media key is
|
|
63
|
+
* config-dependent, so the registry checks that on lookup and lowering resolves
|
|
64
|
+
* the query text — the same split groups use for their state part.
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseContainerModifier(name: string): ContainerModifier | null;
|
|
67
|
+
export declare function createModifierRegistry(view: GrammarConfigView, options?: CreateModifierRegistryOptions): ModifierRegistryResult;
|
|
68
|
+
export {};
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=modifierRegistry.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "AAWA,cAAc,yBAAyB;AAIvC,cAGO,4BACA;KAEF,4BAA4B,sBAAsB,SAAS;AAEhE,iBAAiB,uBAAuB;CACtC,UAAU;;CAEV;;AAGF,iBAAiB,8BAA8B;;;;;;;;;;;;CAY7C,qBAAqB;;;;;;;AAQvB,OAAO,cAAM;;;;;;AAeb,OAAO,iBAAS,gBAAgB;AAIhC,iBAAiB,cAAc;;CAE7B;;CAEA;;;AAIF,OAAO,iBAAS,wBAAwB;;;;;;;;AAsBxC,OAAO,iBAAS,mBAAmB,eAAe;AAYlD,iBAAiB,kBAAkB;;CAEjC;;CAEA;;;;;;;;;;;AAkBF,OAAO,iBAAS,uBAAuB,eAAe;AA6CtD,OAAO,iBAAS,uBACd,MAAM,mBACN,UAAS,gCACR",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/modifierRegistry.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"// The one global modifier namespace the flat value grammar parses against.\n//\n// Built from the existing built-in state vocabulary plus the config's media\n// keys, platform names, and root theme names, with parameterized group\n// modifiers resolved on lookup. There is a single namespace on purpose: a name\n// may mean exactly one thing, so a config whose media key collides with a state\n// or theme name gets a diagnostic instead of a silent choice. Registration order\n// is state, media, platform, theme, and first registration wins.\n//\n// See plans/dom-tailwind-flat-values.md — \"Conditions\".\n\nimport type { GrammarConfigView } from './candidate'\nimport { grammarPlatformNames } from './config'\nimport { coreStateModifierNames, modifierAliases } from './stateModifiers'\nimport { componentStateNames } from './states'\nimport {\n grammarMaxNonPlatformDepth,\n type ModifierKind,\n type ModifierRegistryView,\n} from './valueTypes'\n\ntype Names = readonly string[] | ReadonlySet<string> | Readonly<Record<string, unknown>>\n\nexport interface ModifierRegistryResult {\n registry: ModifierRegistryView\n /** one human-readable line per name collision, in registration order */\n diagnostics: string[]\n}\n\nexport interface CreateModifierRegistryOptions {\n /**\n * The media keys that measure a size, so `@key` is a meaningful container\n * query. A `hover` or `pointer` media key measures nothing a container has, and\n * `@container (hover: none)` is valid syntax with no meaning, so those keys have\n * no `@` form.\n *\n * Overrides the view's derived `containerSizeNames`. When NEITHER is\n * supplied the sizes are unknown: no container modifier registers and a\n * diagnostic says so — an unknowable set refuses rather than over-claims.\n * A caller with genuinely no container concept passes `[]` explicitly.\n */\n containerSizeNames?: Names\n}\n\n/**\n * Every built-in interaction/state modifier spelling: the modifiers of the core\n * pseudo-style props, their aliases, and the component-tier state words the\n * behavior packages expose through DOM attributes.\n */\nexport const stateModifierNames: readonly string[] = Object.freeze([\n ...coreStateModifierNames,\n ...Object.keys(modifierAliases),\n ...componentStateNames,\n])\n\nconst stateModifierSet: ReadonlySet<string> = new Set(stateModifierNames)\n\nconst groupPrefixLength = 'group-'.length\n\n/**\n * Theme conditions name a root theme. Nested themes still inherit from that\n * root, so `dark:` applies within `dark_blue`, but `dark_blue:` is not a\n * condition of its own.\n */\nexport function isRootThemeName(name: string): boolean {\n return name.length > 0 && !name.includes('_')\n}\n\nexport interface GroupModifier {\n /** the state the parent group must be in, always a built-in state modifier */\n state: string\n /** the group name, or null for the nearest unnamed group */\n group: string | null\n}\n\n/** Canonical spelling used by slot identity, precedence, hashing, and matching. */\nexport function canonicalClauseModifier(name: string): string {\n const direct = modifierAliases[name]\n if (direct) return direct\n if (name.startsWith('group-')) {\n const group = parseGroupModifier(name)\n if (group) {\n const state = modifierAliases[group.state] ?? group.state\n if (state !== group.state) {\n return group.group === null ? `group-${state}` : `group-${state}/${group.group}`\n }\n }\n }\n return name\n}\n\n/**\n * Parameterized group modifiers use Tailwind's spelling: `group-hover` for the\n * nearest unnamed group and `group-hover/card` for a named one. The state part\n * must be a built-in state modifier; the name part is an identifier. Returns\n * null for anything else, which is what makes the spelling a single source of\n * truth for both registration and lowering.\n */\nexport function parseGroupModifier(name: string): GroupModifier | null {\n if (!name.startsWith('group-')) return null\n const slash = name.indexOf('/')\n if (slash === -1) {\n const state = name.slice(groupPrefixLength)\n return stateModifierSet.has(state) ? { state, group: null } : null\n }\n if (!isModifierName(name, slash + 1, name.length)) return null\n const state = name.slice(groupPrefixLength, slash)\n return stateModifierSet.has(state) ? { state, group: name.slice(slash + 1) } : null\n}\n\nexport interface ContainerModifier {\n /** the size condition; the registry only accepts a registered media name here */\n size: string\n /** the container name, or null for the nearest container */\n container: string | null\n}\n\ninterface ModifierTrieNode {\n modifiers: readonly string[]\n children: Map<string, ModifierTrieNode>\n next?: readonly string[]\n}\n\n/**\n * Container query modifiers own the `@` prefix: `@sm` targets the nearest\n * container and `@sm/card` a named one (plan decisions 17-18). Plain `sm:` stays\n * a viewport media query, which is why the prefix is reserved.\n *\n * This parses the spelling only. Whether `size` names a registered media key is\n * config-dependent, so the registry checks that on lookup and lowering resolves\n * the query text — the same split groups use for their state part.\n */\nexport function parseContainerModifier(name: string): ContainerModifier | null {\n if (name.charCodeAt(0) !== 64 /* @ */) return null\n const slash = name.indexOf('/')\n if (slash === -1) {\n return isModifierName(name, 1, name.length)\n ? { size: name.slice(1), container: null }\n : null\n }\n if (!isModifierName(name, 1, slash) || !isModifierName(name, slash + 1, name.length)) {\n return null\n }\n return { size: name.slice(1, slash), container: name.slice(slash + 1) }\n}\n\n/** the shared identifier rule for the parameterized parts of a modifier */\nfunction isModifierName(text: string, start: number, end: number): boolean {\n if (start >= end) return false\n for (let index = start; index < end; index++) {\n const code = text.charCodeAt(index)\n if (\n !(code >= 97 && code <= 122) && // a-z\n !(code >= 65 && code <= 90) && // A-Z\n !(code >= 48 && code <= 57) && // 0-9\n code !== 45 && // -\n code !== 95 // _\n ) {\n return false\n }\n }\n return true\n}\n\nfunction forEachName(source: Names | undefined, visit: (name: string) => void): void {\n if (!source) return\n if (Array.isArray(source)) {\n for (const name of source) visit(name)\n return\n }\n if (source instanceof Set) {\n for (const name of source) visit(name)\n return\n }\n for (const name in source as Readonly<Record<string, unknown>>) visit(name)\n}\n\nexport function createModifierRegistry(\n view: GrammarConfigView,\n options: CreateModifierRegistryOptions = {}\n): ModifierRegistryResult {\n const names = new Map<string, ModifierKind>()\n const diagnostics: string[] = []\n const completionNames: string[] = []\n\n // options override the view's derived set. an undefined BOTH falls back to\n // every-media-name for now — that over-claim is scheduled for removal with\n // its own caller sweep; views built from media records already carry the\n // correct derived subset\n const sizeSource = options.containerSizeNames ?? view.containerSizeNames\n let containerSizes: Set<string> | null = null\n if (sizeSource !== undefined) {\n containerSizes = new Set()\n forEachName(sizeSource, (name) => containerSizes!.add(name))\n }\n\n const register = (name: string, kind: ModifierKind): void => {\n if (name.charCodeAt(0) === 64 /* @ */) {\n // the `@` prefix belongs to container queries, so no configured name may\n // take it; otherwise `@sm:` would mean two things\n diagnostics.push(\n `modifier \"${name}\" is not registered: the \"@\" prefix is reserved for container query modifiers, so it cannot be a ${kind} name`\n )\n return\n }\n const existing = names.get(name)\n if (existing !== undefined) {\n if (existing !== kind) {\n diagnostics.push(\n `modifier \"${name}\" is already registered as a ${existing} modifier, so the ${kind} name is ignored`\n )\n }\n return\n }\n if (parseGroupModifier(name) !== null) {\n diagnostics.push(\n `modifier \"${name}\" shadows the group modifier of the same spelling, which can no longer be used as a ${kind} name`\n )\n }\n names.set(name, kind)\n completionNames.push(name)\n }\n\n // when the caller or the view declares which sizes a container can measure,\n // that list is the whole rule. Otherwise any registered media name works\n // (legacy fallback, removal pending its caller sweep)\n const isContainerSize = (size: string): boolean =>\n containerSizes ? containerSizes.has(size) : names.get(size) === 'media'\n\n for (const name of stateModifierNames) register(name, 'state')\n forEachName(view.mediaNames, (name) => register(name, 'media'))\n forEachName(view.platformNames ?? grammarPlatformNames, (name) =>\n register(name, 'platform')\n )\n forEachName(view.themeNames, (name) => {\n if (isRootThemeName(name)) register(name, 'theme')\n })\n\n for (const name of stateModifierNames) {\n const group = `group-${name}`\n if (names.get(group) === undefined) completionNames.push(group)\n }\n if (containerSizes) {\n for (const size of containerSizes) {\n if (isContainerSize(size)) completionNames.push(`@${size}`)\n }\n } else {\n for (const name of completionNames.slice()) {\n if (names.get(name) === 'media') completionNames.push(`@${name}`)\n }\n }\n\n const kindOrder: Readonly<Record<ModifierKind, number>> = {\n platform: 0,\n theme: 1,\n container: 2,\n media: 3,\n group: 4,\n state: 5,\n }\n const modifierTrie: ModifierTrieNode = {\n modifiers: [],\n children: new Map(),\n }\n\n const get = (name: string): ModifierKind | undefined => {\n const kind = names.get(name)\n if (kind !== undefined) return kind\n if (parseGroupModifier(name) !== null) return 'group'\n const container = parseContainerModifier(name)\n if (container !== null && isContainerSize(container.size)) return 'container'\n return undefined\n }\n\n return {\n registry: {\n get,\n next(modifiers: readonly string[]): readonly string[] {\n let node = modifierTrie\n for (const authored of modifiers) {\n const canonical = canonicalClauseModifier(authored)\n let child = node.children.get(canonical)\n if (!child) {\n child = {\n modifiers: [...node.modifiers, canonical],\n children: new Map(),\n }\n node.children.set(canonical, child)\n }\n node = child\n }\n if (node.next) return node.next\n\n const used = new Set<string>()\n const usedKinds = new Set<ModifierKind>()\n let highestOrder = -1\n let nonPlatformDepth = 0\n\n for (const canonical of node.modifiers) {\n if (used.has(canonical)) {\n node.next = []\n return node.next\n }\n used.add(canonical)\n const kind = get(canonical)\n if (!kind || usedKinds.has(kind) || kindOrder[kind] < highestOrder) {\n node.next = []\n return node.next\n }\n usedKinds.add(kind)\n highestOrder = kindOrder[kind]\n if (kind !== 'platform') {\n nonPlatformDepth++\n if (nonPlatformDepth > grammarMaxNonPlatformDepth) {\n node.next = []\n return node.next\n }\n }\n }\n\n const next: string[] = []\n for (const name of completionNames) {\n const canonical = canonicalClauseModifier(name)\n if (canonical !== name) continue\n if (used.has(canonical)) continue\n const kind = get(name)\n if (!kind || kindOrder[kind] < highestOrder) continue\n if (usedKinds.has(kind)) continue\n if (kind !== 'platform' && nonPlatformDepth >= grammarMaxNonPlatformDepth) {\n continue\n }\n next.push(name)\n }\n node.next = next\n return node.next\n },\n },\n diagnostics,\n }\n}\n"
|
|
10
|
+
]
|
|
11
|
+
}
|