@tamagui/create-theme 1.5.9 → 1.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -20,6 +20,7 @@ var src_exports = {};
20
20
  __export(src_exports, {
21
21
  addChildren: () => addChildren,
22
22
  applyMask: () => applyMask,
23
+ createShiftMask: () => createShiftMask,
23
24
  createStrengthenMask: () => createStrengthenMask,
24
25
  createTheme: () => createTheme,
25
26
  createWeakenMask: () => createWeakenMask
@@ -35,7 +36,7 @@ function createTheme(palette, definition, options) {
35
36
  ),
36
37
  ...options == null ? void 0 : options.nonInheritedValues
37
38
  };
38
- THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new WeakMap() });
39
+ THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new Map() });
39
40
  return theme;
40
41
  }
41
42
  const getValue = (palette, value) => {
@@ -57,14 +58,10 @@ function addChildren(themes, getChildren) {
57
58
  }
58
59
  return out;
59
60
  }
60
- const createWeakenMask = ({
61
- by = 1,
62
- max,
63
- min = 0,
64
- inverseNegatives
65
- }) => {
66
- return (template, { skip }) => {
61
+ const createShiftMask = ({ inverse } = {}) => {
62
+ return (template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {
67
63
  const values = Object.entries(template);
64
+ const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity);
68
65
  const out = {};
69
66
  for (const [key, value] of values) {
70
67
  if (typeof value === "string")
@@ -75,18 +72,20 @@ const createWeakenMask = ({
75
72
  }
76
73
  const isPositive = value === 0 ? !isMinusZero(value) : value >= 0;
77
74
  const direction = isPositive ? 1 : -1;
78
- const invert = inverseNegatives && !isPositive ? -1 : 1;
79
- const next = value + by * direction * invert;
75
+ const invert = inverse ? -1 : 1;
76
+ const next = value + strength * direction * invert;
80
77
  const clamped = isPositive ? Math.max(min, Math.min(max, next)) : Math.min(-min, Math.max(-max, next));
81
78
  out[key] = clamped;
82
79
  }
83
80
  return out;
84
81
  };
85
82
  };
83
+ const createWeakenMask = () => createShiftMask();
84
+ const createStrengthenMask = () => createShiftMask({ inverse: true });
86
85
  function isMinusZero(value) {
87
86
  return 1 / value === -Infinity;
88
87
  }
89
- const createStrengthenMask = (props) => createWeakenMask({ ...props, inverseNegatives: true });
88
+ const MaskKeyCache = /* @__PURE__ */ new WeakMap();
90
89
  function applyMask(theme, mask, options = {}) {
91
90
  const info = THEME_INFO.get(theme);
92
91
  if (!info) {
@@ -94,18 +93,51 @@ function applyMask(theme, mask, options = {}) {
94
93
  process.env.NODE_ENV !== "production" ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme` : `\u274C Err2`
95
94
  );
96
95
  }
97
- if (info.cache.has(mask)) {
98
- return info.cache.get(mask);
96
+ const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`;
97
+ MaskKeyCache.set(mask, maskKey);
98
+ const key = `${maskKey}${JSON.stringify(options)}`;
99
+ if (info.cache.has(key)) {
100
+ return info.cache.get(key);
99
101
  }
100
- const template = mask(info.definition, options);
102
+ const template = mask(info.definition, {
103
+ palette: info.palette,
104
+ ...options
105
+ });
101
106
  const next = createTheme(info.palette, template);
102
- info.cache.set(mask, next);
107
+ info.cache.set(key, next);
103
108
  return next;
104
109
  }
110
+ if (process.env.NODE_ENV === "development") {
111
+ const palette = ["0", "1", "2", "3", "-3", "-2", "-1", "-0"];
112
+ const template = { bg: 1, fg: -1 };
113
+ const stongerMask = createStrengthenMask();
114
+ const weakerMask = createWeakenMask();
115
+ const theme = createTheme(palette, template);
116
+ if (theme.bg !== "1")
117
+ throw `\u274C`;
118
+ if (theme.fg !== "-1")
119
+ throw `\u274C`;
120
+ const str = applyMask(theme, stongerMask);
121
+ if (str.bg !== "0")
122
+ throw `\u274C`;
123
+ if (str.fg !== "-0")
124
+ throw `\u274C`;
125
+ const weak = applyMask(theme, weakerMask);
126
+ if (weak.bg !== "2")
127
+ throw `\u274C`;
128
+ if (weak.fg !== "-2")
129
+ throw `\u274C`;
130
+ const weak2 = applyMask(theme, weakerMask, { strength: 2 });
131
+ if (weak2.bg !== "3")
132
+ throw `\u274C`;
133
+ if (weak2.fg !== "-3")
134
+ throw `\u274C`;
135
+ }
105
136
  // Annotate the CommonJS export names for ESM import in node:
106
137
  0 && (module.exports = {
107
138
  addChildren,
108
139
  applyMask,
140
+ createShiftMask,
109
141
  createStrengthenMask,
110
142
  createTheme,
111
143
  createWeakenMask
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.tsx"],
4
- "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\nexport type ShiftMaskProps = { by: number; max: number; min?: number }\nexport type MaskOptions = { skip?: Partial<ThemeMask> }\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: WeakMap<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new WeakMap() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\n// const x = createTheme([], { bg: 1 })\n// const y = addChildren({ x }, (_, x2) => ({\n// y: x,\n// }))\n\nexport const createWeakenMask = ({\n by = 1,\n max,\n min = 0,\n inverseNegatives,\n}: ShiftMaskProps & { inverseNegatives?: boolean }) => {\n return ((template, { skip }) => {\n const values = Object.entries(template) // .filter(Number)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverseNegatives && !isPositive ? -1 : 1\n const next = value + by * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nexport const createStrengthenMask = (props: ShiftMaskProps) =>\n createWeakenMask({ ...props, inverseNegatives: true })\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n if (info.cache.has(mask)) {\n return info.cache.get(mask)\n }\n\n const template = mask(info.definition, options)\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(mask, next)\n\n return next\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,MAAM,aAAa,oBAAI,QAGrB;AAEK,SAAS,YAId,SACA,YACA,SAKA;AACA,QAAM,QAAQ;AAAA,IACZ,GAAI,OAAO;AAAA,MACT,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AAChD,eAAO,CAAC,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,GAAG,mCAAS;AAAA,EACd;AACA,aAAW,IAAI,OAAO,EAAE,SAAS,YAAY,OAAO,oBAAI,QAAQ,EAAE,CAAC;AACnE,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,SAAkB,UAA2B;AAC7D,MAAI,OAAO,UAAU;AAAU,WAAO;AACtC,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,QAAM,OAAO,aAAa,QAAQ,MAAM;AACxC,QAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG;AAC7C,SAAO,QAAQ,KAAK;AACtB;AAWO,SAAS,YAId,QACA,aAGA;AACA,QAAM,MAAM,EAAE,GAAG,OAAO;AACxB,aAAW,OAAO,QAAQ;AACxB,UAAM,YAAY,YAAY,KAAK,OAAO,GAAG,CAAC;AAC9C,eAAW,QAAQ,WAAW;AAC5B,UAAI,GAAG,OAAO,MAAM,IAAI,UAAU,IAAI;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAOO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,KAAK;AAAA,EACL;AAAA,EACA,MAAM;AAAA,EACN;AACF,MAAuD;AACrD,SAAQ,CAAC,UAAU,EAAE,KAAK,MAAM;AAC9B,UAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,UAAM,MAAM,CAAC;AACb,eAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,UAAI,OAAO,UAAU;AAAU;AAC/B,UAAI,QAAQ,OAAO,MAAM;AACvB,YAAI,GAAG,IAAI;AACX;AAAA,MACF;AACA,YAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,YAAM,YAAY,aAAa,IAAI;AACnC,YAAM,SAAS,oBAAoB,CAAC,aAAa,KAAK;AACtD,YAAM,OAAO,QAAQ,KAAK,YAAY;AACtC,YAAM,UAAU,aACZ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,IACjC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;AAEvC,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,OAAO;AAC1B,SAAO,IAAI,UAAU;AACvB;AAEO,MAAM,uBAAuB,CAAC,UACnC,iBAAiB,EAAE,GAAG,OAAO,kBAAkB,KAAK,CAAC;AAEhD,SAAS,UACd,OACA,MACA,UAAuB,CAAC,GACjB;AACP,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR,QAAQ,IAAI,aAAa,eACrB,+GACA;AAAA,IACN;AAAA,EACF;AACA,MAAI,KAAK,MAAM,IAAI,IAAI,GAAG;AACxB,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAEA,QAAM,WAAW,KAAK,KAAK,YAAY,OAAO;AAC9C,QAAM,OAAO,YAAY,KAAK,SAAS,QAAQ;AAE/C,OAAK,MAAM,IAAI,MAAM,IAAI;AAEzB,SAAO;AACT;",
4
+ "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\n\nexport type MaskOptions = {\n palette?: Palette\n skip?: Partial<ThemeMask>\n strength?: number\n max?: number\n min?: number\n}\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: Map<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new Map() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\nexport const createShiftMask = ({ inverse }: { inverse?: boolean } = {}) => {\n return ((template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {\n const values = Object.entries(template)\n const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverse ? -1 : 1\n const next = value + strength * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nexport const createWeakenMask = () => createShiftMask()\nexport const createStrengthenMask = () => createShiftMask({ inverse: true })\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nconst MaskKeyCache = new WeakMap<any, string>()\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n\n const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`\n MaskKeyCache.set(mask, maskKey)\n\n const key = `${maskKey}${JSON.stringify(options)}`\n\n if (info.cache.has(key)) {\n return info.cache.get(key)\n }\n\n const template = mask(info.definition, {\n palette: info.palette,\n ...options,\n })\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(key, next)\n\n return next\n}\n\n// --- tests ---\n\nif (process.env.NODE_ENV === 'development') {\n const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']\n const template = { bg: 1, fg: -1 }\n\n const stongerMask = createStrengthenMask()\n const weakerMask = createWeakenMask()\n\n const theme = createTheme(palette, template)\n if (theme.bg !== '1') throw `\u274C`\n if (theme.fg !== '-1') throw `\u274C`\n\n const str = applyMask(theme, stongerMask)\n if (str.bg !== '0') throw `\u274C`\n if (str.fg !== '-0') throw `\u274C`\n\n const weak = applyMask(theme, weakerMask)\n if (weak.bg !== '2') throw `\u274C`\n if (weak.fg !== '-2') throw `\u274C`\n\n const weak2 = applyMask(theme, weakerMask, { strength: 2 })\n if (weak2.bg !== '3') throw `\u274C`\n if (weak2.fg !== '-3') throw `\u274C`\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,MAAM,aAAa,oBAAI,QAGrB;AAEK,SAAS,YAId,SACA,YACA,SAKA;AACA,QAAM,QAAQ;AAAA,IACZ,GAAI,OAAO;AAAA,MACT,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AAChD,eAAO,CAAC,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,GAAG,mCAAS;AAAA,EACd;AACA,aAAW,IAAI,OAAO,EAAE,SAAS,YAAY,OAAO,oBAAI,IAAI,EAAE,CAAC;AAC/D,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,SAAkB,UAA2B;AAC7D,MAAI,OAAO,UAAU;AAAU,WAAO;AACtC,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,QAAM,OAAO,aAAa,QAAQ,MAAM;AACxC,QAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG;AAC7C,SAAO,QAAQ,KAAK;AACtB;AAWO,SAAS,YAId,QACA,aAGA;AACA,QAAM,MAAM,EAAE,GAAG,OAAO;AACxB,aAAW,OAAO,QAAQ;AACxB,UAAM,YAAY,YAAY,KAAK,OAAO,GAAG,CAAC;AAC9C,eAAW,QAAQ,WAAW;AAC5B,UAAI,GAAG,OAAO,MAAM,IAAI,UAAU,IAAI;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAEO,MAAM,kBAAkB,CAAC,EAAE,QAAQ,IAA2B,CAAC,MAAM;AAC1E,SAAQ,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,GAAG,WAAW,EAAE,MAAM;AAC1E,UAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,UAAM,MAAM,UAAU,UAAU,OAAO,OAAO,OAAO,EAAE,SAAS,IAAI;AACpE,UAAM,MAAM,CAAC;AACb,eAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,UAAI,OAAO,UAAU;AAAU;AAC/B,UAAI,QAAQ,OAAO,MAAM;AACvB,YAAI,GAAG,IAAI;AACX;AAAA,MACF;AACA,YAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,YAAM,YAAY,aAAa,IAAI;AACnC,YAAM,SAAS,UAAU,KAAK;AAC9B,YAAM,OAAO,QAAQ,WAAW,YAAY;AAC5C,YAAM,UAAU,aACZ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,IACjC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;AAEvC,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;AAEO,MAAM,mBAAmB,MAAM,gBAAgB;AAC/C,MAAM,uBAAuB,MAAM,gBAAgB,EAAE,SAAS,KAAK,CAAC;AAE3E,SAAS,YAAY,OAAO;AAC1B,SAAO,IAAI,UAAU;AACvB;AAEA,MAAM,eAAe,oBAAI,QAAqB;AAEvC,SAAS,UACd,OACA,MACA,UAAuB,CAAC,GACjB;AACP,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR,QAAQ,IAAI,aAAa,eACrB,+GACA;AAAA,IACN;AAAA,EACF;AAEA,QAAM,UAAU,aAAa,IAAI,IAAI,KAAK,GAAG,KAAK,OAAO;AACzD,eAAa,IAAI,MAAM,OAAO;AAE9B,QAAM,MAAM,GAAG,UAAU,KAAK,UAAU,OAAO;AAE/C,MAAI,KAAK,MAAM,IAAI,GAAG,GAAG;AACvB,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAEA,QAAM,WAAW,KAAK,KAAK,YAAY;AAAA,IACrC,SAAS,KAAK;AAAA,IACd,GAAG;AAAA,EACL,CAAC;AACD,QAAM,OAAO,YAAY,KAAK,SAAS,QAAQ;AAE/C,OAAK,MAAM,IAAI,KAAK,IAAI;AAExB,SAAO;AACT;AAIA,IAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,QAAM,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,MAAM,MAAM,IAAI;AAC3D,QAAM,WAAW,EAAE,IAAI,GAAG,IAAI,GAAG;AAEjC,QAAM,cAAc,qBAAqB;AACzC,QAAM,aAAa,iBAAiB;AAEpC,QAAM,QAAQ,YAAY,SAAS,QAAQ;AAC3C,MAAI,MAAM,OAAO;AAAK,UAAM;AAC5B,MAAI,MAAM,OAAO;AAAM,UAAM;AAE7B,QAAM,MAAM,UAAU,OAAO,WAAW;AACxC,MAAI,IAAI,OAAO;AAAK,UAAM;AAC1B,MAAI,IAAI,OAAO;AAAM,UAAM;AAE3B,QAAM,OAAO,UAAU,OAAO,UAAU;AACxC,MAAI,KAAK,OAAO;AAAK,UAAM;AAC3B,MAAI,KAAK,OAAO;AAAM,UAAM;AAE5B,QAAM,QAAQ,UAAU,OAAO,YAAY,EAAE,UAAU,EAAE,CAAC;AAC1D,MAAI,MAAM,OAAO;AAAK,UAAM;AAC5B,MAAI,MAAM,OAAO;AAAM,UAAM;AAC/B;",
6
6
  "names": []
7
7
  }
package/dist/esm/index.js CHANGED
@@ -8,7 +8,7 @@ function createTheme(palette, definition, options) {
8
8
  ),
9
9
  ...options == null ? void 0 : options.nonInheritedValues
10
10
  };
11
- THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new WeakMap() });
11
+ THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new Map() });
12
12
  return theme;
13
13
  }
14
14
  const getValue = (palette, value) => {
@@ -30,14 +30,10 @@ function addChildren(themes, getChildren) {
30
30
  }
31
31
  return out;
32
32
  }
33
- const createWeakenMask = ({
34
- by = 1,
35
- max,
36
- min = 0,
37
- inverseNegatives
38
- }) => {
39
- return (template, { skip }) => {
33
+ const createShiftMask = ({ inverse } = {}) => {
34
+ return (template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {
40
35
  const values = Object.entries(template);
36
+ const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity);
41
37
  const out = {};
42
38
  for (const [key, value] of values) {
43
39
  if (typeof value === "string")
@@ -48,18 +44,20 @@ const createWeakenMask = ({
48
44
  }
49
45
  const isPositive = value === 0 ? !isMinusZero(value) : value >= 0;
50
46
  const direction = isPositive ? 1 : -1;
51
- const invert = inverseNegatives && !isPositive ? -1 : 1;
52
- const next = value + by * direction * invert;
47
+ const invert = inverse ? -1 : 1;
48
+ const next = value + strength * direction * invert;
53
49
  const clamped = isPositive ? Math.max(min, Math.min(max, next)) : Math.min(-min, Math.max(-max, next));
54
50
  out[key] = clamped;
55
51
  }
56
52
  return out;
57
53
  };
58
54
  };
55
+ const createWeakenMask = () => createShiftMask();
56
+ const createStrengthenMask = () => createShiftMask({ inverse: true });
59
57
  function isMinusZero(value) {
60
58
  return 1 / value === -Infinity;
61
59
  }
62
- const createStrengthenMask = (props) => createWeakenMask({ ...props, inverseNegatives: true });
60
+ const MaskKeyCache = /* @__PURE__ */ new WeakMap();
63
61
  function applyMask(theme, mask, options = {}) {
64
62
  const info = THEME_INFO.get(theme);
65
63
  if (!info) {
@@ -67,17 +65,50 @@ function applyMask(theme, mask, options = {}) {
67
65
  process.env.NODE_ENV !== "production" ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme` : `\u274C Err2`
68
66
  );
69
67
  }
70
- if (info.cache.has(mask)) {
71
- return info.cache.get(mask);
68
+ const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`;
69
+ MaskKeyCache.set(mask, maskKey);
70
+ const key = `${maskKey}${JSON.stringify(options)}`;
71
+ if (info.cache.has(key)) {
72
+ return info.cache.get(key);
72
73
  }
73
- const template = mask(info.definition, options);
74
+ const template = mask(info.definition, {
75
+ palette: info.palette,
76
+ ...options
77
+ });
74
78
  const next = createTheme(info.palette, template);
75
- info.cache.set(mask, next);
79
+ info.cache.set(key, next);
76
80
  return next;
77
81
  }
82
+ if (process.env.NODE_ENV === "development") {
83
+ const palette = ["0", "1", "2", "3", "-3", "-2", "-1", "-0"];
84
+ const template = { bg: 1, fg: -1 };
85
+ const stongerMask = createStrengthenMask();
86
+ const weakerMask = createWeakenMask();
87
+ const theme = createTheme(palette, template);
88
+ if (theme.bg !== "1")
89
+ throw `\u274C`;
90
+ if (theme.fg !== "-1")
91
+ throw `\u274C`;
92
+ const str = applyMask(theme, stongerMask);
93
+ if (str.bg !== "0")
94
+ throw `\u274C`;
95
+ if (str.fg !== "-0")
96
+ throw `\u274C`;
97
+ const weak = applyMask(theme, weakerMask);
98
+ if (weak.bg !== "2")
99
+ throw `\u274C`;
100
+ if (weak.fg !== "-2")
101
+ throw `\u274C`;
102
+ const weak2 = applyMask(theme, weakerMask, { strength: 2 });
103
+ if (weak2.bg !== "3")
104
+ throw `\u274C`;
105
+ if (weak2.fg !== "-3")
106
+ throw `\u274C`;
107
+ }
78
108
  export {
79
109
  addChildren,
80
110
  applyMask,
111
+ createShiftMask,
81
112
  createStrengthenMask,
82
113
  createTheme,
83
114
  createWeakenMask
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.tsx"],
4
- "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\nexport type ShiftMaskProps = { by: number; max: number; min?: number }\nexport type MaskOptions = { skip?: Partial<ThemeMask> }\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: WeakMap<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new WeakMap() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\n// const x = createTheme([], { bg: 1 })\n// const y = addChildren({ x }, (_, x2) => ({\n// y: x,\n// }))\n\nexport const createWeakenMask = ({\n by = 1,\n max,\n min = 0,\n inverseNegatives,\n}: ShiftMaskProps & { inverseNegatives?: boolean }) => {\n return ((template, { skip }) => {\n const values = Object.entries(template) // .filter(Number)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverseNegatives && !isPositive ? -1 : 1\n const next = value + by * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nexport const createStrengthenMask = (props: ShiftMaskProps) =>\n createWeakenMask({ ...props, inverseNegatives: true })\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n if (info.cache.has(mask)) {\n return info.cache.get(mask)\n }\n\n const template = mask(info.definition, options)\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(mask, next)\n\n return next\n}\n"],
5
- "mappings": "AAUA,MAAM,aAAa,oBAAI,QAGrB;AAEK,SAAS,YAId,SACA,YACA,SAKA;AACA,QAAM,QAAQ;AAAA,IACZ,GAAI,OAAO;AAAA,MACT,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AAChD,eAAO,CAAC,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,GAAG,mCAAS;AAAA,EACd;AACA,aAAW,IAAI,OAAO,EAAE,SAAS,YAAY,OAAO,oBAAI,QAAQ,EAAE,CAAC;AACnE,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,SAAkB,UAA2B;AAC7D,MAAI,OAAO,UAAU;AAAU,WAAO;AACtC,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,QAAM,OAAO,aAAa,QAAQ,MAAM;AACxC,QAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG;AAC7C,SAAO,QAAQ,KAAK;AACtB;AAWO,SAAS,YAId,QACA,aAGA;AACA,QAAM,MAAM,EAAE,GAAG,OAAO;AACxB,aAAW,OAAO,QAAQ;AACxB,UAAM,YAAY,YAAY,KAAK,OAAO,GAAG,CAAC;AAC9C,eAAW,QAAQ,WAAW;AAC5B,UAAI,GAAG,OAAO,MAAM,IAAI,UAAU,IAAI;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAOO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,KAAK;AAAA,EACL;AAAA,EACA,MAAM;AAAA,EACN;AACF,MAAuD;AACrD,SAAQ,CAAC,UAAU,EAAE,KAAK,MAAM;AAC9B,UAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,UAAM,MAAM,CAAC;AACb,eAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,UAAI,OAAO,UAAU;AAAU;AAC/B,UAAI,QAAQ,OAAO,MAAM;AACvB,YAAI,GAAG,IAAI;AACX;AAAA,MACF;AACA,YAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,YAAM,YAAY,aAAa,IAAI;AACnC,YAAM,SAAS,oBAAoB,CAAC,aAAa,KAAK;AACtD,YAAM,OAAO,QAAQ,KAAK,YAAY;AACtC,YAAM,UAAU,aACZ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,IACjC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;AAEvC,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,OAAO;AAC1B,SAAO,IAAI,UAAU;AACvB;AAEO,MAAM,uBAAuB,CAAC,UACnC,iBAAiB,EAAE,GAAG,OAAO,kBAAkB,KAAK,CAAC;AAEhD,SAAS,UACd,OACA,MACA,UAAuB,CAAC,GACjB;AACP,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR,QAAQ,IAAI,aAAa,eACrB,+GACA;AAAA,IACN;AAAA,EACF;AACA,MAAI,KAAK,MAAM,IAAI,IAAI,GAAG;AACxB,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAEA,QAAM,WAAW,KAAK,KAAK,YAAY,OAAO;AAC9C,QAAM,OAAO,YAAY,KAAK,SAAS,QAAQ;AAE/C,OAAK,MAAM,IAAI,MAAM,IAAI;AAEzB,SAAO;AACT;",
4
+ "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\n\nexport type MaskOptions = {\n palette?: Palette\n skip?: Partial<ThemeMask>\n strength?: number\n max?: number\n min?: number\n}\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: Map<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new Map() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\nexport const createShiftMask = ({ inverse }: { inverse?: boolean } = {}) => {\n return ((template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {\n const values = Object.entries(template)\n const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverse ? -1 : 1\n const next = value + strength * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nexport const createWeakenMask = () => createShiftMask()\nexport const createStrengthenMask = () => createShiftMask({ inverse: true })\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nconst MaskKeyCache = new WeakMap<any, string>()\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n\n const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`\n MaskKeyCache.set(mask, maskKey)\n\n const key = `${maskKey}${JSON.stringify(options)}`\n\n if (info.cache.has(key)) {\n return info.cache.get(key)\n }\n\n const template = mask(info.definition, {\n palette: info.palette,\n ...options,\n })\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(key, next)\n\n return next\n}\n\n// --- tests ---\n\nif (process.env.NODE_ENV === 'development') {\n const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']\n const template = { bg: 1, fg: -1 }\n\n const stongerMask = createStrengthenMask()\n const weakerMask = createWeakenMask()\n\n const theme = createTheme(palette, template)\n if (theme.bg !== '1') throw `\u274C`\n if (theme.fg !== '-1') throw `\u274C`\n\n const str = applyMask(theme, stongerMask)\n if (str.bg !== '0') throw `\u274C`\n if (str.fg !== '-0') throw `\u274C`\n\n const weak = applyMask(theme, weakerMask)\n if (weak.bg !== '2') throw `\u274C`\n if (weak.fg !== '-2') throw `\u274C`\n\n const weak2 = applyMask(theme, weakerMask, { strength: 2 })\n if (weak2.bg !== '3') throw `\u274C`\n if (weak2.fg !== '-3') throw `\u274C`\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -8,7 +8,7 @@ function createTheme(palette, definition, options) {
8
8
  ),
9
9
  ...options == null ? void 0 : options.nonInheritedValues
10
10
  };
11
- THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new WeakMap() });
11
+ THEME_INFO.set(theme, { palette, definition, cache: /* @__PURE__ */ new Map() });
12
12
  return theme;
13
13
  }
14
14
  const getValue = (palette, value) => {
@@ -30,14 +30,10 @@ function addChildren(themes, getChildren) {
30
30
  }
31
31
  return out;
32
32
  }
33
- const createWeakenMask = ({
34
- by = 1,
35
- max,
36
- min = 0,
37
- inverseNegatives
38
- }) => {
39
- return (template, { skip }) => {
33
+ const createShiftMask = ({ inverse } = {}) => {
34
+ return (template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {
40
35
  const values = Object.entries(template);
36
+ const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity);
41
37
  const out = {};
42
38
  for (const [key, value] of values) {
43
39
  if (typeof value === "string")
@@ -48,18 +44,20 @@ const createWeakenMask = ({
48
44
  }
49
45
  const isPositive = value === 0 ? !isMinusZero(value) : value >= 0;
50
46
  const direction = isPositive ? 1 : -1;
51
- const invert = inverseNegatives && !isPositive ? -1 : 1;
52
- const next = value + by * direction * invert;
47
+ const invert = inverse ? -1 : 1;
48
+ const next = value + strength * direction * invert;
53
49
  const clamped = isPositive ? Math.max(min, Math.min(max, next)) : Math.min(-min, Math.max(-max, next));
54
50
  out[key] = clamped;
55
51
  }
56
52
  return out;
57
53
  };
58
54
  };
55
+ const createWeakenMask = () => createShiftMask();
56
+ const createStrengthenMask = () => createShiftMask({ inverse: true });
59
57
  function isMinusZero(value) {
60
58
  return 1 / value === -Infinity;
61
59
  }
62
- const createStrengthenMask = (props) => createWeakenMask({ ...props, inverseNegatives: true });
60
+ const MaskKeyCache = /* @__PURE__ */ new WeakMap();
63
61
  function applyMask(theme, mask, options = {}) {
64
62
  const info = THEME_INFO.get(theme);
65
63
  if (!info) {
@@ -67,17 +65,50 @@ function applyMask(theme, mask, options = {}) {
67
65
  process.env.NODE_ENV !== "production" ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme` : `\u274C Err2`
68
66
  );
69
67
  }
70
- if (info.cache.has(mask)) {
71
- return info.cache.get(mask);
68
+ const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`;
69
+ MaskKeyCache.set(mask, maskKey);
70
+ const key = `${maskKey}${JSON.stringify(options)}`;
71
+ if (info.cache.has(key)) {
72
+ return info.cache.get(key);
72
73
  }
73
- const template = mask(info.definition, options);
74
+ const template = mask(info.definition, {
75
+ palette: info.palette,
76
+ ...options
77
+ });
74
78
  const next = createTheme(info.palette, template);
75
- info.cache.set(mask, next);
79
+ info.cache.set(key, next);
76
80
  return next;
77
81
  }
82
+ if (process.env.NODE_ENV === "development") {
83
+ const palette = ["0", "1", "2", "3", "-3", "-2", "-1", "-0"];
84
+ const template = { bg: 1, fg: -1 };
85
+ const stongerMask = createStrengthenMask();
86
+ const weakerMask = createWeakenMask();
87
+ const theme = createTheme(palette, template);
88
+ if (theme.bg !== "1")
89
+ throw `\u274C`;
90
+ if (theme.fg !== "-1")
91
+ throw `\u274C`;
92
+ const str = applyMask(theme, stongerMask);
93
+ if (str.bg !== "0")
94
+ throw `\u274C`;
95
+ if (str.fg !== "-0")
96
+ throw `\u274C`;
97
+ const weak = applyMask(theme, weakerMask);
98
+ if (weak.bg !== "2")
99
+ throw `\u274C`;
100
+ if (weak.fg !== "-2")
101
+ throw `\u274C`;
102
+ const weak2 = applyMask(theme, weakerMask, { strength: 2 });
103
+ if (weak2.bg !== "3")
104
+ throw `\u274C`;
105
+ if (weak2.fg !== "-3")
106
+ throw `\u274C`;
107
+ }
78
108
  export {
79
109
  addChildren,
80
110
  applyMask,
111
+ createShiftMask,
81
112
  createStrengthenMask,
82
113
  createTheme,
83
114
  createWeakenMask
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.tsx"],
4
- "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\nexport type ShiftMaskProps = { by: number; max: number; min?: number }\nexport type MaskOptions = { skip?: Partial<ThemeMask> }\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: WeakMap<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new WeakMap() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\n// const x = createTheme([], { bg: 1 })\n// const y = addChildren({ x }, (_, x2) => ({\n// y: x,\n// }))\n\nexport const createWeakenMask = ({\n by = 1,\n max,\n min = 0,\n inverseNegatives,\n}: ShiftMaskProps & { inverseNegatives?: boolean }) => {\n return ((template, { skip }) => {\n const values = Object.entries(template) // .filter(Number)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverseNegatives && !isPositive ? -1 : 1\n const next = value + by * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nexport const createStrengthenMask = (props: ShiftMaskProps) =>\n createWeakenMask({ ...props, inverseNegatives: true })\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n if (info.cache.has(mask)) {\n return info.cache.get(mask)\n }\n\n const template = mask(info.definition, options)\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(mask, next)\n\n return next\n}\n"],
5
- "mappings": "AAUA,MAAM,aAAa,oBAAI,QAGrB;AAEK,SAAS,YAId,SACA,YACA,SAKA;AACA,QAAM,QAAQ;AAAA,IACZ,GAAI,OAAO;AAAA,MACT,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AAChD,eAAO,CAAC,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,GAAG,mCAAS;AAAA,EACd;AACA,aAAW,IAAI,OAAO,EAAE,SAAS,YAAY,OAAO,oBAAI,QAAQ,EAAE,CAAC;AACnE,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,SAAkB,UAA2B;AAC7D,MAAI,OAAO,UAAU;AAAU,WAAO;AACtC,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,QAAM,OAAO,aAAa,QAAQ,MAAM;AACxC,QAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG;AAC7C,SAAO,QAAQ,KAAK;AACtB;AAWO,SAAS,YAId,QACA,aAGA;AACA,QAAM,MAAM,EAAE,GAAG,OAAO;AACxB,aAAW,OAAO,QAAQ;AACxB,UAAM,YAAY,YAAY,KAAK,OAAO,GAAG,CAAC;AAC9C,eAAW,QAAQ,WAAW;AAC5B,UAAI,GAAG,OAAO,MAAM,IAAI,UAAU,IAAI;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;AAOO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,KAAK;AAAA,EACL;AAAA,EACA,MAAM;AAAA,EACN;AACF,MAAuD;AACrD,SAAQ,CAAC,UAAU,EAAE,KAAK,MAAM;AAC9B,UAAM,SAAS,OAAO,QAAQ,QAAQ;AACtC,UAAM,MAAM,CAAC;AACb,eAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,UAAI,OAAO,UAAU;AAAU;AAC/B,UAAI,QAAQ,OAAO,MAAM;AACvB,YAAI,GAAG,IAAI;AACX;AAAA,MACF;AACA,YAAM,aAAa,UAAU,IAAI,CAAC,YAAY,KAAK,IAAI,SAAS;AAChE,YAAM,YAAY,aAAa,IAAI;AACnC,YAAM,SAAS,oBAAoB,CAAC,aAAa,KAAK;AACtD,YAAM,OAAO,QAAQ,KAAK,YAAY;AACtC,YAAM,UAAU,aACZ,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,IACjC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;AAEvC,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,OAAO;AAC1B,SAAO,IAAI,UAAU;AACvB;AAEO,MAAM,uBAAuB,CAAC,UACnC,iBAAiB,EAAE,GAAG,OAAO,kBAAkB,KAAK,CAAC;AAEhD,SAAS,UACd,OACA,MACA,UAAuB,CAAC,GACjB;AACP,QAAM,OAAO,WAAW,IAAI,KAAK;AACjC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI;AAAA,MACR,QAAQ,IAAI,aAAa,eACrB,+GACA;AAAA,IACN;AAAA,EACF;AACA,MAAI,KAAK,MAAM,IAAI,IAAI,GAAG;AACxB,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAEA,QAAM,WAAW,KAAK,KAAK,YAAY,OAAO;AAC9C,QAAM,OAAO,YAAY,KAAK,SAAS,QAAQ;AAE/C,OAAK,MAAM,IAAI,MAAM,IAAI;AAEzB,SAAO;AACT;",
4
+ "sourcesContent": ["import type { Variable } from '@tamagui/web'\n\nexport type ThemeMask = Record<string, string | number>\nexport type Palette = string[]\n\nexport type MaskOptions = {\n palette?: Palette\n skip?: Partial<ThemeMask>\n strength?: number\n max?: number\n min?: number\n}\n\ntype GenericTheme = { [key: string]: string | Variable }\ntype CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A\n\nconst THEME_INFO = new WeakMap<\n any,\n { palette: Palette; definition: ThemeMask; cache: Map<any, any> }\n>()\n\nexport function createTheme<\n Definition extends ThemeMask,\n Extras extends Record<string, string> = {}\n>(\n palette: Palette,\n definition: Definition,\n options?: {\n nonInheritedValues?: Extras\n }\n): {\n [key in keyof Definition | keyof Extras]: string\n} {\n const theme = {\n ...(Object.fromEntries(\n Object.entries(definition).map(([key, offset]) => {\n return [key, getValue(palette, offset)]\n })\n ) as any),\n ...options?.nonInheritedValues,\n }\n THEME_INFO.set(theme, { palette, definition, cache: new Map() })\n return theme\n}\n\nconst getValue = (palette: Palette, value: string | number) => {\n if (typeof value === 'string') return value\n const max = palette.length - 1\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const next = isPositive ? value : max + value\n const index = Math.min(Math.max(0, next), max)\n return palette[index]\n}\n\ntype SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string\n ? ParentKeys\n : never}_${ChildKeys extends string ? ChildKeys : never}`\n\ntype ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (\n name: Name,\n theme: Theme\n) => { [key: string]: Theme }\n\nexport function addChildren<\n Themes extends { [key: string]: GenericTheme },\n GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>\n>(\n themes: Themes,\n getChildren: GetChildren\n): Themes & {\n [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]\n} {\n const out = { ...themes }\n for (const key in themes) {\n const subThemes = getChildren(key, themes[key])\n for (const sKey in subThemes) {\n out[`${key}_${sKey}`] = subThemes[sKey] as any\n }\n }\n return out as any\n}\n\nexport const createShiftMask = ({ inverse }: { inverse?: boolean } = {}) => {\n return ((template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {\n const values = Object.entries(template)\n const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)\n const out = {}\n for (const [key, value] of values) {\n if (typeof value === 'string') continue\n if (skip && key in skip) {\n out[key] = value\n continue\n }\n const isPositive = value === 0 ? !isMinusZero(value) : value >= 0\n const direction = isPositive ? 1 : -1\n const invert = inverse ? -1 : 1\n const next = value + strength * direction * invert\n const clamped = isPositive\n ? Math.max(min, Math.min(max, next))\n : Math.min(-min, Math.max(-max, next))\n\n out[key] = clamped\n }\n return out as typeof template\n }) as CreateMask\n}\n\nexport const createWeakenMask = () => createShiftMask()\nexport const createStrengthenMask = () => createShiftMask({ inverse: true })\n\nfunction isMinusZero(value) {\n return 1 / value === -Infinity\n}\n\nconst MaskKeyCache = new WeakMap<any, string>()\n\nexport function applyMask<Theme extends GenericTheme>(\n theme: Theme,\n mask: CreateMask,\n options: MaskOptions = {}\n): Theme {\n const info = THEME_INFO.get(theme)\n if (!info) {\n throw new Error(\n process.env.NODE_ENV !== 'production'\n ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`\n : `\u274C Err2`\n )\n }\n\n const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`\n MaskKeyCache.set(mask, maskKey)\n\n const key = `${maskKey}${JSON.stringify(options)}`\n\n if (info.cache.has(key)) {\n return info.cache.get(key)\n }\n\n const template = mask(info.definition, {\n palette: info.palette,\n ...options,\n })\n const next = createTheme(info.palette, template) as Theme\n\n info.cache.set(key, next)\n\n return next\n}\n\n// --- tests ---\n\nif (process.env.NODE_ENV === 'development') {\n const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']\n const template = { bg: 1, fg: -1 }\n\n const stongerMask = createStrengthenMask()\n const weakerMask = createWeakenMask()\n\n const theme = createTheme(palette, template)\n if (theme.bg !== '1') throw `\u274C`\n if (theme.fg !== '-1') throw `\u274C`\n\n const str = applyMask(theme, stongerMask)\n if (str.bg !== '0') throw `\u274C`\n if (str.fg !== '-0') throw `\u274C`\n\n const weak = applyMask(theme, weakerMask)\n if (weak.bg !== '2') throw `\u274C`\n if (weak.fg !== '-2') throw `\u274C`\n\n const weak2 = applyMask(theme, weakerMask, { strength: 2 })\n if (weak2.bg !== '3') throw `\u274C`\n if (weak2.fg !== '-3') throw `\u274C`\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/create-theme",
3
- "version": "1.5.9",
3
+ "version": "1.5.10",
4
4
  "types": "./types/index.d.ts",
5
5
  "main": "dist/cjs",
6
6
  "module": "dist/esm",
@@ -27,10 +27,10 @@
27
27
  }
28
28
  },
29
29
  "dependencies": {
30
- "@tamagui/web": "^1.5.9"
30
+ "@tamagui/web": "^1.5.10"
31
31
  },
32
32
  "devDependencies": {
33
- "@tamagui/build": "^1.5.9"
33
+ "@tamagui/build": "^1.5.10"
34
34
  },
35
35
  "publishConfig": {
36
36
  "access": "public"
package/src/index.tsx CHANGED
@@ -2,15 +2,21 @@ import type { Variable } from '@tamagui/web'
2
2
 
3
3
  export type ThemeMask = Record<string, string | number>
4
4
  export type Palette = string[]
5
- export type ShiftMaskProps = { by: number; max: number; min?: number }
6
- export type MaskOptions = { skip?: Partial<ThemeMask> }
5
+
6
+ export type MaskOptions = {
7
+ palette?: Palette
8
+ skip?: Partial<ThemeMask>
9
+ strength?: number
10
+ max?: number
11
+ min?: number
12
+ }
7
13
 
8
14
  type GenericTheme = { [key: string]: string | Variable }
9
15
  type CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A
10
16
 
11
17
  const THEME_INFO = new WeakMap<
12
18
  any,
13
- { palette: Palette; definition: ThemeMask; cache: WeakMap<any, any> }
19
+ { palette: Palette; definition: ThemeMask; cache: Map<any, any> }
14
20
  >()
15
21
 
16
22
  export function createTheme<
@@ -33,7 +39,7 @@ export function createTheme<
33
39
  ) as any),
34
40
  ...options?.nonInheritedValues,
35
41
  }
36
- THEME_INFO.set(theme, { palette, definition, cache: new WeakMap() })
42
+ THEME_INFO.set(theme, { palette, definition, cache: new Map() })
37
43
  return theme
38
44
  }
39
45
 
@@ -74,19 +80,10 @@ export function addChildren<
74
80
  return out as any
75
81
  }
76
82
 
77
- // const x = createTheme([], { bg: 1 })
78
- // const y = addChildren({ x }, (_, x2) => ({
79
- // y: x,
80
- // }))
81
-
82
- export const createWeakenMask = ({
83
- by = 1,
84
- max,
85
- min = 0,
86
- inverseNegatives,
87
- }: ShiftMaskProps & { inverseNegatives?: boolean }) => {
88
- return ((template, { skip }) => {
89
- const values = Object.entries(template) // .filter(Number)
83
+ export const createShiftMask = ({ inverse }: { inverse?: boolean } = {}) => {
84
+ return ((template, { skip, max: maxIn, palette, min = 0, strength = 1 }) => {
85
+ const values = Object.entries(template)
86
+ const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)
90
87
  const out = {}
91
88
  for (const [key, value] of values) {
92
89
  if (typeof value === 'string') continue
@@ -96,8 +93,8 @@ export const createWeakenMask = ({
96
93
  }
97
94
  const isPositive = value === 0 ? !isMinusZero(value) : value >= 0
98
95
  const direction = isPositive ? 1 : -1
99
- const invert = inverseNegatives && !isPositive ? -1 : 1
100
- const next = value + by * direction * invert
96
+ const invert = inverse ? -1 : 1
97
+ const next = value + strength * direction * invert
101
98
  const clamped = isPositive
102
99
  ? Math.max(min, Math.min(max, next))
103
100
  : Math.min(-min, Math.max(-max, next))
@@ -108,12 +105,14 @@ export const createWeakenMask = ({
108
105
  }) as CreateMask
109
106
  }
110
107
 
108
+ export const createWeakenMask = () => createShiftMask()
109
+ export const createStrengthenMask = () => createShiftMask({ inverse: true })
110
+
111
111
  function isMinusZero(value) {
112
112
  return 1 / value === -Infinity
113
113
  }
114
114
 
115
- export const createStrengthenMask = (props: ShiftMaskProps) =>
116
- createWeakenMask({ ...props, inverseNegatives: true })
115
+ const MaskKeyCache = new WeakMap<any, string>()
117
116
 
118
117
  export function applyMask<Theme extends GenericTheme>(
119
118
  theme: Theme,
@@ -128,14 +127,49 @@ export function applyMask<Theme extends GenericTheme>(
128
127
  : `❌ Err2`
129
128
  )
130
129
  }
131
- if (info.cache.has(mask)) {
132
- return info.cache.get(mask)
130
+
131
+ const maskKey = MaskKeyCache.get(mask) ?? `${Math.random()}`
132
+ MaskKeyCache.set(mask, maskKey)
133
+
134
+ const key = `${maskKey}${JSON.stringify(options)}`
135
+
136
+ if (info.cache.has(key)) {
137
+ return info.cache.get(key)
133
138
  }
134
139
 
135
- const template = mask(info.definition, options)
140
+ const template = mask(info.definition, {
141
+ palette: info.palette,
142
+ ...options,
143
+ })
136
144
  const next = createTheme(info.palette, template) as Theme
137
145
 
138
- info.cache.set(mask, next)
146
+ info.cache.set(key, next)
139
147
 
140
148
  return next
141
149
  }
150
+
151
+ // --- tests ---
152
+
153
+ if (process.env.NODE_ENV === 'development') {
154
+ const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']
155
+ const template = { bg: 1, fg: -1 }
156
+
157
+ const stongerMask = createStrengthenMask()
158
+ const weakerMask = createWeakenMask()
159
+
160
+ const theme = createTheme(palette, template)
161
+ if (theme.bg !== '1') throw `❌`
162
+ if (theme.fg !== '-1') throw `❌`
163
+
164
+ const str = applyMask(theme, stongerMask)
165
+ if (str.bg !== '0') throw `❌`
166
+ if (str.fg !== '-0') throw `❌`
167
+
168
+ const weak = applyMask(theme, weakerMask)
169
+ if (weak.bg !== '2') throw `❌`
170
+ if (weak.fg !== '-2') throw `❌`
171
+
172
+ const weak2 = applyMask(theme, weakerMask, { strength: 2 })
173
+ if (weak2.bg !== '3') throw `❌`
174
+ if (weak2.fg !== '-3') throw `❌`
175
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTheme.d.ts","sourceRoot":"","sources":["../src/createTheme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,OAAO,GAAG,MAAM,EAAE,CAAA;AAC9B,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACtE,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;CAAE,CAAA;AAEvD,KAAK,YAAY,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAA;AACxD,KAAK,UAAU,GAAG,CAAC,CAAC,SAAS,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,KAAK,CAAC,CAAA;AAO/E,wBAAgB,WAAW,CACzB,UAAU,SAAS,SAAS,EAC5B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,EAE1C,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE;IACR,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,GACA;KACA,GAAG,IAAI,MAAM,UAAU,GAAG,MAAM,MAAM,GAAG,MAAM;CACjD,CAWA;AAWD,KAAK,YAAY,CAAC,UAAU,EAAE,SAAS,IAAI,GAAG,UAAU,SAAS,MAAM,GACnE,UAAU,GACV,KAAK,IAAI,SAAS,SAAS,MAAM,GAAG,SAAS,GAAG,KAAK,EAAE,CAAA;AAE3D,wBAAgB,WAAW,CACzB,KAAK,SAAS,YAAY,EAC1B,MAAM,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,EACvC,WAAW,SAAS,CAAC,IAAI,EAAE,MAAM,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,EAElF,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACvB,MAAM,GAAG;KACT,GAAG,IAAI,YAAY,CAAC,MAAM,MAAM,EAAE,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC,GAAG,KAAK;CAC1E,CASA;AAED,eAAO,MAAM,gBAAgB;;gBA2B5B,CAAA;AAMD,eAAO,MAAM,oBAAoB,UAAW,cAAc,eACF,CAAA;AAExD,wBAAgB,SAAS,CAAC,KAAK,SAAS,YAAY,EAClD,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,WAAgB,GACxB,KAAK,CAmBP"}
package/types/index.d.ts CHANGED
@@ -1,13 +1,12 @@
1
1
  import type { Variable } from '@tamagui/web';
2
2
  export type ThemeMask = Record<string, string | number>;
3
3
  export type Palette = string[];
4
- export type ShiftMaskProps = {
5
- by: number;
6
- max: number;
7
- min?: number;
8
- };
9
4
  export type MaskOptions = {
5
+ palette?: Palette;
10
6
  skip?: Partial<ThemeMask>;
7
+ strength?: number;
8
+ max?: number;
9
+ min?: number;
11
10
  };
12
11
  type GenericTheme = {
13
12
  [key: string]: string | Variable;
@@ -27,10 +26,11 @@ export declare function addChildren<Themes extends {
27
26
  }, GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>>(themes: Themes, getChildren: GetChildren): Themes & {
28
27
  [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes];
29
28
  };
30
- export declare const createWeakenMask: ({ by, max, min, inverseNegatives, }: ShiftMaskProps & {
31
- inverseNegatives?: boolean | undefined;
29
+ export declare const createShiftMask: ({ inverse }?: {
30
+ inverse?: boolean | undefined;
32
31
  }) => CreateMask;
33
- export declare const createStrengthenMask: (props: ShiftMaskProps) => CreateMask;
32
+ export declare const createWeakenMask: () => CreateMask;
33
+ export declare const createStrengthenMask: () => CreateMask;
34
34
  export declare function applyMask<Theme extends GenericTheme>(theme: Theme, mask: CreateMask, options?: MaskOptions): Theme;
35
35
  export {};
36
36
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,OAAO,GAAG,MAAM,EAAE,CAAA;AAE9B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,KAAK,YAAY,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAA;AACxD,KAAK,UAAU,GAAG,CAAC,CAAC,SAAS,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,KAAK,CAAC,CAAA;AAO/E,wBAAgB,WAAW,CACzB,UAAU,SAAS,SAAS,EAC5B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,EAE1C,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE;IACR,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,GACA;KACA,GAAG,IAAI,MAAM,UAAU,GAAG,MAAM,MAAM,GAAG,MAAM;CACjD,CAWA;AAWD,KAAK,YAAY,CAAC,UAAU,EAAE,SAAS,IAAI,GAAG,UAAU,SAAS,MAAM,GACnE,UAAU,GACV,KAAK,IAAI,SAAS,SAAS,MAAM,GAAG,SAAS,GAAG,KAAK,EAAE,CAAA;AAE3D,KAAK,WAAW,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,SAAS,YAAY,IAAI,CACpF,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,KACT;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,CAAA;AAE7B,wBAAgB,WAAW,CACzB,MAAM,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,EAC9C,WAAW,SAAS,WAAW,CAAC,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,EAEnE,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACvB,MAAM,GAAG;KACT,GAAG,IAAI,YAAY,CAAC,MAAM,MAAM,EAAE,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,MAAM,CAAC;CACzF,CASA;AAED,eAAO,MAAM,eAAe;;gBAuB3B,CAAA;AAED,eAAO,MAAM,gBAAgB,kBAA0B,CAAA;AACvD,eAAO,MAAM,oBAAoB,kBAA2C,CAAA;AAQ5E,wBAAgB,SAAS,CAAC,KAAK,SAAS,YAAY,EAClD,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,WAAgB,GACxB,KAAK,CA4BP"}