diff --git a/bin/token.ts b/bin/token.ts index 6fc8153..8146737 100644 --- a/bin/token.ts +++ b/bin/token.ts @@ -1,29 +1,10 @@ -/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable no-restricted-syntax */ import { createWriteStream } from 'node:fs'; import { PassThrough } from 'node:stream'; import { parseArgs } from 'node:util'; import { camelCase } from 'change-case'; import { leafNodeMapper, type PathStr, type VarFn, vargEx } from './utils.js'; -import { - formControlTokens, - globalTokens, - panelTokens, - propsTokens, -} from '#defaults'; -import { - badgeVars, - badgeVarsMapFnPrefix, - buttonVars, - buttonVarsMapFnPrefix, - formControlVarsMapFnPrefix, - globalVars, - globalVarsMapFnPrefix, - panelVars, - panelVarsMapFnPrefix, - propsVars, - propsVarsMapFnPrefix, -} from '#vars'; +import { vars, tokens } from '#vars'; const { values: { type, outputPath }, @@ -40,19 +21,14 @@ const { }, }, }); + /** * vars */ const knownVars = new Map(); -for (const [vars, prefix] of [ - [globalVars, globalVarsMapFnPrefix] as const, - [propsVars, propsVarsMapFnPrefix] as const, - [panelVars, panelVarsMapFnPrefix] as const, - [badgeVars, badgeVarsMapFnPrefix] as const, - [buttonVars, buttonVarsMapFnPrefix] as const, -]) { +for (const [prefix, v] of Object.entries(vars)) { leafNodeMapper( - vars, + v, (path, value) => { knownVars.set(value, { path }); }, @@ -60,19 +36,14 @@ for (const [vars, prefix] of [ ); } -/** +/* * tokens */ const knownTokens = new Map(); -for (const [vars, prefix] of [ - [globalTokens, globalVarsMapFnPrefix] as const, - [propsTokens, propsVarsMapFnPrefix] as const, - [panelTokens, panelVarsMapFnPrefix] as const, - [formControlTokens, formControlVarsMapFnPrefix] as const, -]) { +for (const [prefix, t] of Object.entries(tokens)) { leafNodeMapper( - vars, + t, (path, value) => { knownTokens.set(path, { value }); }, diff --git a/lib/css-helpers.ts b/lib/css-helpers.ts index f18155d..2fb40b8 100644 --- a/lib/css-helpers.ts +++ b/lib/css-helpers.ts @@ -1,8 +1,8 @@ import { calc } from '@vanilla-extract/css-utils'; -export function createGlobalThemeMapFn(prefix = '') { - const delim = '-'; - const fullPrefix = prefix ? `${prefix}${delim}` : ''; +export function createGlobalThemeMapFn(prefix: T) { + const delim = '-' as const; + const fullPrefix = prefix ? (`${prefix}${delim}` as const) : ('' as const); return Object.assign( (value: string | null, path: Array) => `${fullPrefix}${value}${path.join(delim)}`, diff --git a/lib/defaults.ts b/lib/defaults.ts deleted file mode 100644 index a25f066..0000000 --- a/lib/defaults.ts +++ /dev/null @@ -1,133 +0,0 @@ -import type { MapLeafNodes } from '@vanilla-extract/css'; -import * as openPropsTokens from './generated/open-props-tokens.js'; -import { - type formControlVars, - globalVars, - type panelVars, - propsVars, - type textLinkVars, - textVariantVars, -} from './vars.css.js'; - -export const globalTokens = { - border: { - radius: openPropsTokens.radius2, - width: openPropsTokens.borderSize2, - }, -} satisfies MapLeafNodes, string>; - -export const propsTokens = { - border: { - width: { - 0: '0', - 1: '0.05rem', - 2: '0.15rem', - 3: '0.2rem', - 4: '0.3rem', - 5: '0.5rem', - 6: '0.75rem', - 7: '1rem', - }, - }, - radius: { - // these are tuned to be distinguished at DPR3 but may not be different at - // lower densities they are rem so they dont scale with text size NOTE: we - // may need some `em` ones if we need fully curved buttons "pill" style - 0: '0', - 1: '0.125rem', - 2: '0.25rem', - 3: '0.5rem', - 50: '50%', - }, - space: { - '000': '-.5rem', - '00': '-.25rem', - '0': '0rem', - '1': '.125rem', - '2': '.25rem', - '3': '.375rem', - '4': '.5rem', - '5': '.625rem', - '6': '.75rem', - '7': '1rem', - '8': '1.25rem', - '9': '1.5rem', - '10': '1.75rem', - '11': '2rem', - '12': '3rem', - '13': '5rem', - '14': '7.5rem', - '15': '10rem', - '16': '15rem', - }, -} satisfies MapLeafNodes; - -export const defaultTextTokens = { - fontWeight: { - light: '300', - normal: '400', - medium: '500', - semibold: '600', - bold: '700', - } satisfies Record, -}; - -export const defaultTextLinkTokens = { - strong: { - fontWeight: textVariantVars.fontWeight.medium, - rest: { - fgColor: globalVars.color.accent, - textDecoration: 'underline', - }, - hover: { - fgColor: globalVars.color.accent, - textDecoration: 'underline', - }, - }, - normal: { - fontWeight: textVariantVars.fontWeight.normal, - rest: { - fgColor: globalVars.color.accent, - textDecoration: 'none', - }, - hover: { - fgColor: globalVars.color.accent, - textDecoration: 'underline', - }, - }, - weak: { - fontWeight: textVariantVars.fontWeight.normal, - rest: { - fgColor: globalVars.color.fgColor, - textDecoration: 'underline', - }, - hover: { - fgColor: globalVars.color.accent, - textDecoration: 'underline', - }, - }, - none: { - fontWeight: 'inherit', - rest: { - fgColor: 'inherit', - textDecoration: 'none', - }, - hover: { - fgColor: 'inherit', - textDecoration: 'none', - }, - }, -} satisfies MapLeafNodes; - -export const formControlTokens = { - outline: { - width: openPropsTokens.borderSize1, - }, -} satisfies MapLeafNodes; - -export const panelTokens = { - padding: { - inline: openPropsTokens.size3, - block: propsVars.space['4'], - }, -} satisfies MapLeafNodes; diff --git a/lib/main.ts b/lib/main.ts index 0616156..c513916 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -22,4 +22,4 @@ export * from './icons.js'; export * from './virtual.js'; export * from './panel.js'; -export type { ReactHTMLElementsHacked } from './types.js'; +export type { ReactHTMLElementsHacked, Falsy } from './types.js'; diff --git a/lib/tokens.ts b/lib/tokens.ts new file mode 100644 index 0000000..3770f09 --- /dev/null +++ b/lib/tokens.ts @@ -0,0 +1,276 @@ +import type { MapLeafNodes } from '@vanilla-extract/css'; +import * as openPropsTokens from './generated/open-props-tokens.js'; +import { + type calloutVars, + type formControlVars, + globalVars, + type panelVars, + type propsVars, + type textLinkVars, + textVariantVars, +} from './vars.css.js'; + +export const defaultGlobalTokens = { + border: { + radius: openPropsTokens.radius2, + width: openPropsTokens.borderSize2, + }, + color: { + brand: openPropsTokens.gray5, + accent: openPropsTokens.gray7, + fgColor: openPropsTokens.gray1, + bgColor: openPropsTokens.gray9, + borderColor: openPropsTokens.gray3, + muted: { + fgColor: openPropsTokens.gray4, + bgColor: openPropsTokens.gray8, + borderColor: openPropsTokens.gray5, + }, + emphasis: { + fgColor: openPropsTokens.gray1, + bgColor: openPropsTokens.gray7, + borderColor: openPropsTokens.gray7, + }, + }, +} satisfies MapLeafNodes; + +export const defaultPropsTokens = { + border: { + width: { + 0: '0', + 1: '0.05rem', + 2: '0.15rem', + 3: '0.2rem', + 4: '0.3rem', + 5: '0.5rem', + 6: '0.75rem', + 7: '1rem', + }, + }, + radius: { + // these are tuned to be distinguished at DPR3 but may not be different at + // lower densities they are rem so they dont scale with text size NOTE: we + // may need some `em` ones if we need fully curved buttons "pill" style + 0: '0', + 1: '0.125rem', + 2: '0.25rem', + 3: '0.5rem', + 50: '50%', + }, + space: { + '000': '-.5rem', + '00': '-.25rem', + '0': '0rem', + '1': '.125rem', + '2': '.25rem', + '3': '.375rem', + '4': '.5rem', + '5': '.625rem', + '6': '.75rem', + '7': '1rem', + '8': '1.25rem', + '9': '1.5rem', + '10': '1.75rem', + '11': '2rem', + '12': '3rem', + '13': '5rem', + '14': '7.5rem', + '15': '10rem', + '16': '15rem', + }, +} satisfies MapLeafNodes; + +// capSize: { +// '0': { +// fontSize: '0.625rem', +// lineHeight: '1rem', +// baselineTrim: '0.125rem', +// capHeightTrim: '0.125rem', +// }, +// } +// .../ +// to 6, body, small etc + +export const defaultTextTokens = { + capSize: { + '00': { + fontSize: '0.625rem', + lineHeight: '1rem', + baselineTrim: '0.125rem', + capHeightTrim: '0.125rem', + }, + '0': { + fontSize: '0.625rem', + lineHeight: '1rem', + baselineTrim: '0.125rem', + capHeightTrim: '0.125rem', + }, + '1': { + fontSize: '0.75rem', + lineHeight: '1.25rem', + baselineTrim: '0.125rem', + capHeightTrim: '0.125rem', + }, + '2': { + fontSize: '0.875rem', + lineHeight: '1.5rem', + baselineTrim: '0.125rem', + capHeightTrim: '0.125rem', + }, + '3': { + fontSize: '1rem', + lineHeight: '1.5rem', + baselineTrim: '0.25rem', + capHeightTrim: '0.25rem', + }, + '4': { + fontSize: '1.25rem', + lineHeight: '1.75rem', + baselineTrim: '0.25rem', + capHeightTrim: '0.25rem', + }, + '5': { + fontSize: '1.5rem', + lineHeight: '2rem', + baselineTrim: '0.25rem', + capHeightTrim: '0.25rem', + }, + '6': { + fontSize: '2rem', + lineHeight: '2.5rem', + baselineTrim: '0.25rem', + capHeightTrim: '0.25rem', + }, + body: { + fontSize: '1rem', + lineHeight: '1.5rem', + baselineTrim: '0.25rem', + capHeightTrim: '0.25rem', + }, + small: { + fontSize: '0.875rem', + lineHeight: '1.25rem', + baselineTrim: '0.125rem', + capHeightTrim: '0.125rem', + }, + }, + + fontWeight: { + light: '300', + normal: '400', + medium: '500', + semibold: '600', + bold: '700', + }, + lineHeight: { + heading: '1.25', + normal: '1.5', + paragraph: '1.75', + }, + size: { + '00': { + fontSize: '0.625rem', + lineHeight: '1rem', + }, + '0': { + fontSize: '0.75rem', + lineHeight: '1.25rem', + }, + '1': { + fontSize: '0.875rem', + lineHeight: '1.5rem', + }, + '2': { + fontSize: '1rem', + lineHeight: '1.5rem', + }, + '3': { + fontSize: '1.25rem', + lineHeight: '1.75rem', + }, + '4': { + fontSize: '1.5rem', + lineHeight: '2rem', + }, + '5': { + fontSize: '2rem', + lineHeight: '2.5rem', + }, + '6': { + fontSize: '3rem', + lineHeight: '3.5rem', + }, + body: { + fontSize: '1rem', + lineHeight: '1.5rem', + }, + small: { + fontSize: '0.875rem', + lineHeight: '1.25rem', + }, + }, +} satisfies MapLeafNodes; + +export const defaultTextLinkTokens = { + strong: { + fontWeight: textVariantVars.fontWeight.medium, + rest: { + fgColor: globalVars.color.accent, + textDecoration: 'underline', + }, + hover: { + fgColor: globalVars.color.accent, + textDecoration: 'underline', + }, + }, + normal: { + fontWeight: textVariantVars.fontWeight.normal, + rest: { + fgColor: globalVars.color.accent, + textDecoration: 'none', + }, + hover: { + fgColor: globalVars.color.accent, + textDecoration: 'underline', + }, + }, + weak: { + fontWeight: textVariantVars.fontWeight.normal, + rest: { + fgColor: globalVars.color.fgColor, + textDecoration: 'underline', + }, + hover: { + fgColor: globalVars.color.accent, + textDecoration: 'underline', + }, + }, + none: { + fontWeight: 'inherit', + rest: { + fgColor: 'inherit', + textDecoration: 'none', + }, + hover: { + fgColor: 'inherit', + textDecoration: 'none', + }, + }, +} satisfies MapLeafNodes; + +export const formControlTokens = { + outline: { + width: openPropsTokens.borderSize1, + }, +} satisfies MapLeafNodes; + +export const panelTokens = { + padding: { + inline: openPropsTokens.size3, + block: openPropsTokens.size4, + }, +} satisfies MapLeafNodes; + +export const calloutTokens = { + padding: openPropsTokens.size4, +} satisfies MapLeafNodes; diff --git a/lib/typography.tsx b/lib/typography.tsx index 43d93bb..83d8056 100644 --- a/lib/typography.tsx +++ b/lib/typography.tsx @@ -16,23 +16,22 @@ export type { FontSize, FontWeight, LineHeight, TextWrap }; export type CommonTextProps = { secondary?: true | Falsy; + flexDirection?: never; + flexWrap?: never; + space?: never; + overflow?: never; }; export type ParagraphProps = - Omit< - Merge, CommonTextProps>, - 'flexDirection' | 'flexWrap' | 'space' | 'overflow' | 'capSize' - >; + Merge, CommonTextProps>; export type ExactTextProps = - Omit< - Merge, CommonTextProps>, - 'flexDirection' | 'flexWrap' | 'space' | 'overflow' | 'fontSize' - >; + Merge, CommonTextProps>; -export type HeadingProps = ParagraphProps & { - level?: HeadingLevel; -}; +export type HeadingProps = Merge< + BoxProps, + CommonTextProps & { level?: HeadingLevel } +>; function headingProps(level: HeadingLevel): HeadingProps { switch (level) { diff --git a/lib/vars.css.ts b/lib/vars.css.ts index f668258..1daf495 100644 --- a/lib/vars.css.ts +++ b/lib/vars.css.ts @@ -3,7 +3,18 @@ import { createGlobalThemeMapFn } from './css-helpers.js'; import type { LinkVariant } from './link.css.js'; import type { FontSize, FontWeight, LineHeight } from './typography.css.js'; -export const globalVarsMapFnPrefix = ''; +export type Prefix = + | '' + | 'callout' + | 'button' + | 'panel' + | 'formControl' + | 'props' + | 'text' + | 'textlink'; +// | 'badge' + +export const globalVarsMapFnPrefix = '' satisfies Prefix; export const globalVars = createGlobalThemeContract( { color: { @@ -34,7 +45,7 @@ export const globalVars = createGlobalThemeContract( /** * Props vars */ -export const propsVarsMapFnPrefix = 'props'; +export const propsVarsMapFnPrefix = 'props' satisfies Prefix; export const propsVars = createGlobalThemeContract( { border: { @@ -84,7 +95,7 @@ export const propsVars = createGlobalThemeContract( /** * Callout vars */ -export const calloutVarsMapFnPrefix = 'callout'; +export const calloutVarsMapFnPrefix = 'callout' satisfies Prefix; export const calloutVars = createGlobalThemeContract( { // border: { @@ -99,7 +110,7 @@ export const calloutVars = createGlobalThemeContract( /** * Button vars */ -export const buttonVarsMapFnPrefix = 'button'; +export const buttonVarsMapFnPrefix = 'button' satisfies Prefix; export const buttonVars = createGlobalThemeContract( { // border: { @@ -110,24 +121,24 @@ export const buttonVars = createGlobalThemeContract( createGlobalThemeMapFn(buttonVarsMapFnPrefix), ); -/** - * Badge vars - */ -export const badgeVarsMapFnPrefix = 'badge'; -export const badgeVars = createGlobalThemeContract( - { - // border: { - // radius: '', - // width: '', - // }, - }, - createGlobalThemeMapFn(badgeVarsMapFnPrefix), -); +// /** +// * Badge vars +// */ +// export const badgeVarsMapFnPrefix = 'badge' satisfies Prefix; +// export const badgeVars = createGlobalThemeContract( +// { +// // border: { +// // radius: '', +// // width: '', +// // }, +// }, +// createGlobalThemeMapFn(badgeVarsMapFnPrefix), +// ); /** * Panel vars */ -export const panelVarsMapFnPrefix = 'panel'; +export const panelVarsMapFnPrefix = 'panel' satisfies Prefix; export const panelVars = createGlobalThemeContract( { // border: { @@ -145,7 +156,7 @@ export const panelVars = createGlobalThemeContract( /** * Form control vars */ -export const formControlVarsMapFnPrefix = 'formControl'; +export const formControlVarsMapFnPrefix = 'formControl' satisfies Prefix; export const formControlVars = createGlobalThemeContract( { // border: { @@ -175,7 +186,7 @@ const fontSizeShape = { lineHeight: '', }; -export const textVarsMapFnPrefix = 'text'; +export const textVarsMapFnPrefix = 'text' satisfies Prefix; export const textVariantVars = createGlobalThemeContract( { lineHeight: { @@ -221,7 +232,7 @@ export const textVariantVars = createGlobalThemeContract( /** * text links vars */ -export const textLinkVarsMapFnPrefix = 'textlink'; +export const textLinkVarsMapFnPrefix = 'textlink' satisfies Prefix; export const textLinkVars = createGlobalThemeContract( { strong: { diff --git a/lib/vars.ts b/lib/vars.ts index 3f1d581..6dd9fe3 100644 --- a/lib/vars.ts +++ b/lib/vars.ts @@ -1,56 +1,61 @@ +import type { CSSVarFunction, MapLeafNodes } from '@vanilla-extract/css'; import { + defaultGlobalTokens, + defaultPropsTokens, defaultTextLinkTokens, defaultTextTokens, formControlTokens, - globalTokens, panelTokens, - propsTokens, -} from './defaults.js'; +} from './tokens.js'; import { - formControlVars, - globalVars, - panelVars, - propsVars, - textLinkVars, - textVariantVars, -} from './vars.css.js'; - -export { - badgeVars, - badgeVarsMapFnPrefix, buttonVars, buttonVarsMapFnPrefix, + calloutVars, + calloutVarsMapFnPrefix, + formControlVars, formControlVarsMapFnPrefix, globalVars, globalVarsMapFnPrefix, panelVars, panelVarsMapFnPrefix, + type Prefix, propsVars, propsVarsMapFnPrefix, + textLinkVars, + textLinkVarsMapFnPrefix, + textVariantVars, + textVarsMapFnPrefix, } from './vars.css.js'; +type TokenPrimitive = string | CSSVarFunction; +type TokenValue = TokenPrimitive | TokenObject; +type TokenObject = { [Key in string]: TokenValue }; + +type VarValue = CSSVarFunction | VarObject; +type VarObject = { [Key in string]: VarValue }; + export const vars = { - global: { - border: globalVars.border, - }, - panel: panelVars, - formControl: formControlVars, - props: propsVars, - text: { - fontWeight: textVariantVars.fontWeight, - }, - textLinks: textLinkVars, -}; + [globalVarsMapFnPrefix]: globalVars, + [panelVarsMapFnPrefix]: panelVars, + [formControlVarsMapFnPrefix]: formControlVars, + [propsVarsMapFnPrefix]: propsVars, + [textVarsMapFnPrefix]: textVariantVars, + [textLinkVarsMapFnPrefix]: textLinkVars, + [buttonVarsMapFnPrefix]: buttonVars, + [calloutVarsMapFnPrefix]: calloutVars, + // [badgeVarsMapFnPrefix]: badgeVars, +} satisfies Record; export const tokens = { - global: { - border: globalTokens.border, - }, - panel: panelTokens, - formControl: formControlTokens, - props: propsTokens, - text: { - fontWeight: defaultTextTokens.fontWeight, + [globalVarsMapFnPrefix]: defaultGlobalTokens, + [panelVarsMapFnPrefix]: panelTokens, + [formControlVarsMapFnPrefix]: formControlTokens, + [propsVarsMapFnPrefix]: defaultPropsTokens, + [textVarsMapFnPrefix]: defaultTextTokens, + [textLinkVarsMapFnPrefix]: defaultTextLinkTokens, + [buttonVarsMapFnPrefix]: {}, + [calloutVarsMapFnPrefix]: { + padding: '1rem', }, - textLinks: defaultTextLinkTokens, -}; + // [badgeVarsMapFnPrefix]: {} as TokenObject, +} satisfies MapLeafNodes; diff --git a/package.json b/package.json index db76e8e..6c76777 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,6 @@ "#vars": { "types": "./dist/lib/vars.d.ts", "default": "./build/vars.js" - }, - "#defaults": { - "types": "./dist/lib/defaults.d.ts", - "default": "./dist/lib/defaults.js" } }, "exports": { @@ -50,6 +46,9 @@ "preversion": "make test" }, "dependencies": { + "@floating-ui/dom": "^1.6.5", + "@floating-ui/react": "^0.26.17", + "@floating-ui/react-dom": "^2.1.0", "clsx": "^2.1.1", "js-cookie": "^3.0.5" }, @@ -109,9 +108,6 @@ "vitest": "^1.6.0" }, "peerDependencies": { - "@floating-ui/dom": "^1.6.5", - "@floating-ui/react": "^0.26.17", - "@floating-ui/react-dom": "^2.1.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vanilla-extract/css": "^1.15.3",