chore: version packages - #253
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@tenphi/tasty@3.0.0
Major Changes
#227
097bfc5Thanks @tenphi! - At-rule naming consistency.'@fontFace'and'@counterStyle'style keys to'@font-face'and'@counter-style'so they match the real CSS at-rule names Tasty already emits. Emitted CSS is unchanged;@startingis unaffected.fontFace→fontFacesandcounterStyle→counterStylesfor consistency with the other plural collections (properties,functions,keyframes). The injector methods (injector.fontFace()/injector.counterStyle()) and hooks (useFontFace/useCounterStyle) are unchanged.Both are breaking renames. Update styles-object keys from
'@fontFace'/'@counterStyle'to'@font-face'/'@counter-style', andconfigure({ fontFace, counterStyle })toconfigure({ fontFaces, counterStyles }).#227
097bfc5Thanks @tenphi! - A style group that names direction modifiers now takes a single value.Values and modifiers are bucketed separately per comma group, so the interleaving that
padding: '2x 4x top right'suggests never survived parsing:'2x top 4x right'and'top 2x right 4x'were the same input, and the pairing was decided by the order the modifiers happened to appear in.'1x 2x right top'and'1x 2x top right'produced different CSS, and'1x 2x top top'silently assignedtoptwice.A group that names directions now applies its first value to every direction it names, and extra values are ignored with a development-mode warning (silent in production, never throws). Per-side values come from comma-separated groups:
Affects
padding,margin,inset,scrollMargin, andfade.Unchanged: single-value directional groups (
padding: '2x top','1x left right'), every value-only CSS shorthand form (padding: '1x 2x','1x 2x 3x 4x', and nowfade: '3x 1x'too — a group that names no direction is unambiguous and keeps plain shorthand order), CSS-wide keywords, and thelonghandmodifier.inset'sdockmodifier keeps its two-value form, with sharper semantics: the first value applies to the named edge and the second to the perpendicular sides it spans, soinset: '2x 4x bottom dock'still givesauto 32px 16px 32px. A third value withdock, or a second value without it, now warns.dockisinset-only, sopadding,margin, andscrollMarginget the strict one-value rule with no exception.#227
097bfc5Thanks @tenphi! - Rename the per-component/per-recipe'@properties'style key to'@property'so it matches the real CSS at-rule name (@property), which is what Tasty already emits. The emitted CSS (@property --name { ... }) is unchanged. The global config fieldconfigure({ properties })and theautoPropertyTypesflag are unchanged — only the styles-object key is renamed.This is a breaking rename for any styles using
'@properties': { ... }; update those keys to'@property'.#227
097bfc5Thanks @tenphi! - ## v3 consistency passFinishes the renames the rest of the v3 cleanup started, removes what was never meant to be public, and fixes a class of bug where a second
configure()call discarded the first one's values.Repeated
configure()now merges instead of replacingrecipes,keyframes,properties,fontFaces,counterStyles, and CSS@functiondefinitions replaced wholesale, whiletokensandglobalStylesmerged. A design-systemconfigure()followed by an applicationconfigure()therefore silently dropped the design system's recipes, keyframes, properties, font faces, counter styles, and functions. All of them now merge, with the later call winning on a key conflict — matching what thefunctionsdocumentation already claimed.configure({ polyfills })gains thestylesGeneratedguard every sibling option has, and shallow-merges, so an unrelated laterconfigure({ polyfills: {} })no longer switches a polyfill off while an explicit{ functions: false }still does.funcs→functionson the parser surfaceParserOptions.funcs→ParserOptions.functionsStyleParser.setFuncs()→StyleParser.setFunctions()Removed from the public surface
customFunc,getGlobalFuncs,resetGlobalFuncs— useconfigure({ functions }).getGlobalFuncs()returned the live mutable internal registry, and writing to it bypassed the parser's cache invalidation, so the write silently never took effect. They remain internally ascustomFunction,getGlobalParseFunctions, andresetGlobalParseFunctions.setGlobalPredefinedTokens,resetGlobalPredefinedTokens— useconfigure({ replaceTokens })andresetConfig().warn,deprecationWarning— internal helpers with no callers.DEFAULT_PLUGINS— never consumed by anything, includingconfigure(). Passing it toconfigure({ plugins })was a no-op; the defaultokhsl/okhstfunctions are registered by the parser bootstrap, which is unchanged. Also removes the unusedareDefaultFunctionsRegistered()and_resetDefaultFunctionsFlag().registerDefaultFunctions— internal bootstrap helper.GlobalStyledProps— an interface whose only member was thebreakpointsprop already removed as dead.The
@tenphi/tasty/corebarrel now lists theutils/stylesexports explicitly instead of re-exporting the whole module, so internal helpers can no longer leak onto the public surface by accident.Renamed
CssOptions→CSSOptions, matching thegetCSSText/useRawCSSfamily. It was newly exported in this major, so this is its first released spelling.Added
FunctionsConfigandParseFunctionare now exported. They are the declared types of the publicfunctionsconfig and plugin fields, so they were impossible to reference.Fixed
okhsl/okhst/createColorFunc"expected 3 values" warning fired in production and used an[okhsl]prefix. It is now development-only and follows the[Tasty]convention:[Tasty] okhsl(): expected 3 values (H S L), got: ….functionssaidfunction.RESERVED_PREFIXESin the state parser now includes@font-face,@counter-style, and@function, matching the built-in state list.useFunctionJSDoc and thedocs/react-api.mdexample showed the function being called from a raw inlinestyleprop, which bypasses the parser entirely — the$$name(...)sugar is never expanded, and underpolyfills.functionsit silently does nothing. Both now show the DSL call.Guardrails
A new public-API snapshot test records every export of every
package.jsonsubpath insrc/__snapshots__/public-api.md, covering types as well as values. Any change to the published surface now shows up as a reviewable diff.knipis now correct and runs in CI. It previously declared only test and bench files as entry points, so it could not reason about the published surface at all — which is why the dead exports above went unnoticed.#227
097bfc5Thanks @tenphi! - ## v3 public API cleanupConsolidated breaking changes for the v3 major release. At-rule styles-object keys stay CSS-spec-faithful (
@keyframes,@property,@font-face,@counter-style,@function,@starting); thefuncinjector method stays abbreviated (functionis a reserved word). Everything else is unified to JS conventions (plural where applicable), dead code is removed, and type-vs-runtime gaps are fixed.Breaking renames
getCssText()/getCssTextForNode()/StyleInjector.getCssTextForClasses()→getCSSText()/getCSSTextForNode()/getCSSTextForClasses()to match the rest of the raw-CSS family (useRawCSS,injectRawCSS,getRawCSSText).getGlobalFontFace→getGlobalFontFaces,getGlobalCounterStyle→getGlobalCounterStyles,getGlobalFunction→getGlobalFunctions.okhslFunc/okhstFunc→okhslFunction/okhstFunction(align with theuseFunction/FunctionDefinitionfamily).@tenphi/tasty/next→@tenphi/tasty/zero/next(it already lived under thezeronamespace; this avoids colliding with@tenphi/tasty/ssr/next).Removed from the public surface
getIsTestEnvironment()— useisTestEnvironment()directly.hydrateTastyCache()(deprecated since 2.x) — usehydrateTastyClasses().setMiddlewareTransferCache()/getMiddlewareTransferCache()—@internal-tagged helpers moved off the public@tenphi/tasty/ssr/astroexport.clearWriterCache()— test utility removed from the@tenphi/tasty/babel-pluginexport (still importable internally).UseStylesOptionstype alias —useStyles()is now typedStyles | undefineddirectly.PropertyOptions(the duplicate defined in the injector barrel) — consolidated into a singlePropertyOptionsininjector/types(PropertyDefinition+root?).UsePropertyOptionsis now an alias of it.Bucketenum — un-exported from@tenphi/tasty/core(parser-internal).Props(Record<string, any>) — un-exported; inlineRecord<string, any>at the wrap-overload base.BaseProps/TastySpecificKeys:css,block,inline,breakpoints(typed but never consumed).Behavior / type fixes
themeprop is now implemented: it maps to thedata-themeattribute on the rendered element (previously it fell through tootherPropsand was spread raw). AugmentTastyThemeNamesfor autocomplete.isCheckedadded toBaseProps/AllBaseProps(it already worked at runtime via theis*pipeline but was missing from the root prop types).tasty(Component, options)(wrap overload) no longer leaks factory-only options (variants,elements,styleProps,modProps,tokenProps) onto the wrapped component as runtime props — they are stripped, matching the element factory.namePrefixJSDoc regex corrected to^[a-zA-Z_][a-zA-Z0-9_-]{0,31}$(matches the validator).Additive (still part of this major's API surface)
createServerStyleCollector()andcreateCSSWriter()factory wrappers are now the canonical entry points for the infrastructure services (the classes remain exported for advanced use).TastyComponentPropsWithDefaults, thetastyDebughelper types (DebugOptions,CssOptions,InspectResult,CacheStatus,ChunkBreakdown,Summary,DebugChunkInfo), andPropertyOptionsare now exported. The debug-localChunkInfowas renamedDebugChunkInfoto avoid colliding with the parserChunkInfo.Minor Changes
#227
097bfc5Thanks @tenphi! - Add support for the CSS@functionat-rule (custom functions), unify function configuration under a singlefunctionskey, and add an opt-in@functionpolyfill.Define reusable, parameterized CSS functions via the
'@function'styles key, theuseFunctionhook, orconfigure({ functions }). Functions are defined with$$namekeys and invoked with the$$name(...)sugar (e.g.marginTop: '$$negative(10px)'). Parameters and local variables use$name, andresult/defaults/local-var values flow through the Tasty DSL (units, color tokens, auto-calc, fallbacks). Works across client, SSR/RSC, and zero-runtime (tastyStatic) modes. Functions are injected once, globally, and never cleaned up (like@counter-style). A component-local@functiondefinition overrides a globalconfigure()definition of the same name.Unified
functionsconfig (breaking for the previously-shippedfuncs/functionkeys): the separatefuncs(JS parse-time functions) andfunction(declarative CSS functions) config and plugin keys are replaced by a singlefunctionsmap, discriminated by value type — a bare key with a function value is a parse function (name(...)), and a$$namekey with an object value is a CSS@functiondefinition ($$name(...)). A key whose prefix doesn't match its value type is ignored with a dev-mode warning.@functionpolyfill: enableconfigure({ polyfills: { functions: true } })to inline every$$name(...)call into plain CSS (calc()/var()/color-mix()) at parse time instead of emitting the native@functionrule. This brings@functionsupport to browsers that don't ship the at-rule yet (Firefox/Safari) and works across all rendering modes. Limitations: no native fallback, conditional results are inlined verbatim, typed params/returnsare dropped, and recursive functions are left untouched.Note: native
@functionis an experimental CSS feature; without the polyfill, unsupported browsers safely ignore the rule.#227
097bfc5Thanks @tenphi! - Custom color functions now work as ordinary plugins with no core special-casing.Previously
okhsl/okhstwere hardcoded across the style core (parser,strToRgb,resolveToRgbaValues,#token.alphainjection, and the fast-path color check), so a third-party color plugin could not achieve the same integration without editing Tasty itself.The core now treats any custom
functionsentry whose output is an already-supported color (rgb,hsl,#…,oklch, …) as a first-class color value by delegating back to the parser. All okhsl/okhst special-casing has been removed; they are now ordinary one-liner plugins registered by default (backward compatible — zero-config usage is unchanged).New public exports for plugin authors:
createColorFunc(helper for HSL-style color spaces) andresolveFunctionColor. A third-party color plugin is now just:createColorFunc's signature changed from(name, channelLabel, convert)to(name, convert, label?)— the label is now an optional trailing argument used only to format dev warnings.#227
097bfc5Thanks @tenphi! - Add props middleware and global base style props, and make custom style handlers unambiguous.configure({ propHandlers })registers middleware over component props — props in, props out. It is the extension point for props that are not style properties: read a custom prop, strip it so it never reaches the DOM, and fold its meaning intostyles,mods,tokens,variant, oras.The map key is the handler's name and, by default, the prop that triggers it — an absent prop costs one property check, not a call. Use
['*', fn]for an unconditional handler or[['a', 'b'], fn]to trigger on any of several props. Handlers run in registration order (plugins first, then direct config), each receiving the previous one's output, and run before any prop is destructured, so a handler can rewrite every tasty prop. Returning nothing is treated as "unchanged" with a development-mode warning, since it is almost always a forgottenreturn props.Handlers must be pure and must not mutate their input: style values are cached by object identity, so mutating one in place produces a stale class name and stale CSS. Memoize the styles you build per input value — this also lets the cache key reuse its serialization instead of recomputing it every render.
Not applicable to zero-runtime mode:
tastyStatic()takes styles objects, not props, so there is nothing for middleware to run on. Components rendered throughtasty()are unaffected and get their CSS from the runtime injector as usual. Server and client must register the same handlers, or class names diverge and hydration mismatches — the same requirement asnamePrefix.configure({ baseStyleProps })exposes style properties as top-level props on every tasty component, without each component listing them instyleProps:Base style props are now resolved lazily per component and refreshed when the registry changes, so
configure()may run after your components are defined — previously the prop list was fixed when eachtasty()factory was created, which happens at module load.Type both with module augmentation:
TastyCustomPropsforpropHandlerskeys, andTastyBaseStylePropNames(each name set totrue) for promoted style names, which are then typed exactly like the style they name. Both plugins andconfigure()can supplypropHandlersandbaseStyleProps.Plugins can now also supply
properties,keyframes,fontFaces, andcounterStyles. A plugin whose handler or prop handler emits a custom property usually needs an@propertydeclaration alongside it, which previously could only come fromconfigure()directly. All four merge with theconfigure()values, with direct config winning on conflict.Custom style handlers are safer and better typed.
configure({ handlers: { fill } })also took overimageand the wholebackground-*family, andconfigure({ handlers: { display } })took downflow,gap,hide,overflow,whiteSpace, andtextOverflow— and the displaced names did not go dark, they silently fell back to auto-generated CSS aliases, sohide: truebegan emitting a literalhide: truedeclaration.defineHandler(deps, fn)infers each dependency's type from the dependency list, so a typo in the destructure is a type error rather than a silentundefined.StyleHandlerProps,ResolvedStyleValue, andAnyStyleHandlertypes.RawStyleHandlerandStyleHandlertake an optional props type parameter, and the handler dependency map is now typed as the resolved scalars handlers actually receive rather than a state map — which removes the blanket@ts-expect-errorthe built-in registry needed.CSSMapaccepts the numeric values built-in handlers already returned ({ '-webkit-line-clamp': 3 }), and a handler that returns a camelCase CSS property name now emits aHANDLER_CAMEL_CASE_KEYwarning in development instead of silently producing a declaration the browser ignores.--custom-propertynames are exempt, being case-sensitive.docs/configuration.mdnow documents the handler return shape, the$selector-suffix key, that values arrive as raw unparsed DSL strings, the shared-handler groups, and chunk membership.Patch Changes
#227
097bfc5Thanks @tenphi! - Typefadeas acceptingtrue, and document it.fade: truealready worked — an empty value list falls back tocalc(2 * var(--gap)), a default that follows the gap token and which no explicit value can express (fade: '2x'bakes in a static16px). But the prop type wasstringonly,docs/ai-agents.mdlistedfadeamong the properties that rejecttrue, and the ESLint plugin flagged it. Three of the four sources disagreed with the implementation.Surfaced by
@cube-dev/ui-kit, whoseFadeAllDirectionsstory relies on it.