@sanity/themer

0.8.10.9.0
dist/themes-Bxgltjmb.js.map
+dist/themes-Bxgltjmb.js.mapNew file
+1
Index: package/dist/themes-Bxgltjmb.js.map
===================================================================
--- package/dist/themes-Bxgltjmb.js.map
+++ package/dist/themes-Bxgltjmb.js.map
@@ -0,0 +1,1 @@
+{"version":3,"file":"themes-Bxgltjmb.js","names":["\"default\""],"sources":["../src/tool/constants.ts","../src/tool/ViewTransitions.css.ts","../src/tool/addThemerTransitionType.ts","../src/tool/themes.ts"],"sourcesContent":["export const MIN_MEDIA_INDEX_FOR_SPLIT_SCREEN = 3\n/**\n * The Studio navbar's root, the `Card` that draws its bottom border — its\n * test id is stable and unique to the navbar, unlike its `data-ui` name\n */\nexport const NAVBAR_SELECTOR = '[data-testid=\"studio-navbar\"]'\n","import {\n  createViewTransition,\n  globalStyle,\n  keyframes,\n  style,\n  type GlobalStyleRule,\n} from '@vanilla-extract/css'\nimport type {ViewTransitionClass} from 'react'\n\nfunction createViewTransitionType(\n  rules: Partial<Record<'new' | 'old' | 'group' | 'imagePair', GlobalStyleRule>>,\n  debugId?: string,\n) {\n  const type = style({}, debugId)\n  if (rules.new) {\n    globalStyle(`::view-transition-new(.${type})`, rules.new)\n  }\n  if (rules.old) {\n    globalStyle(`::view-transition-old(.${type})`, rules.old)\n  }\n  if (rules.group) {\n    globalStyle(`::view-transition-group(.${type})`, rules.group)\n  }\n  if (rules.imagePair) {\n    globalStyle(`::view-transition-image-pair(.${type})`, rules.imagePair)\n  }\n  return type\n}\n\n/**\n * The transition type of the layout's motions — what `ThemerLayout` adds to\n * every transition it starts, and React passes on to the view transition.\n * `:active-view-transition-type()` tells the layout's transitions from any\n * other on the page while they run.\n *\n * It's used on all transition types that userland might want to participate in, for example by setting their own:\n * ```tsx\n * <ViewTransition update={{'sanity-themer': 'auto', default: 'none'}}>\n * ```\n */\nexport const layoutTransitionType = 'sanity-themer'\n\n/**\n * Used with addTransitionType, and on `update` props on <ViewTransition> as the object key\n */\nexport const viewTransitionTypes = {\n  'open': createViewTransition('open'),\n  'close': createViewTransition('close'),\n  'split-screen:open': createViewTransition('split-screen-open'),\n  'split-screen:close': createViewTransition('split-screen-close'),\n  'crossfade': createViewTransition('crossfade'),\n}\n\nconst navbarButtonUpdateTransition = createViewTransitionType({\n  new: {animation: 'none'},\n  old: {display: 'none'},\n})\n\nconst resizeStudioRules = {inlineSize: '100%', blockSize: '100%', objectFit: 'fill'} as const\nconst resizeStudioTransition = createViewTransitionType(\n  {old: resizeStudioRules, new: resizeStudioRules},\n  'resizeStudio',\n)\n\nconst splitScreenFilter = 'blur(12px)'\nconst splitStudioTransition = createViewTransitionType({\n  old: {\n    ...resizeStudioRules,\n    animationName: keyframes({to: {opacity: 0, filter: splitScreenFilter}}),\n  },\n  new: {\n    ...resizeStudioRules,\n    animationName: keyframes({from: {opacity: 0, filter: splitScreenFilter}}),\n  },\n})\n/**\n * The split copy slides in from the side, or out to it — hidden for the first\n * quarter of the way in, and for the last quarter of the way out\n */\nconst splitScreenSlideIn = keyframes({\n  'from': {transform: 'translateX(-100%)', opacity: 0},\n  '25%': {opacity: 0},\n})\nconst splitScreenSlideOut = keyframes({\n  'to': {transform: 'translateX(-100%)', opacity: 0},\n  '75%': {opacity: 0},\n})\n\nexport const viewTransitionClasses = {\n  navbarButton: {\n    update: {\n      [viewTransitionTypes['split-screen:open']]: 'none',\n      [viewTransitionTypes['split-screen:close']]: 'none',\n      [viewTransitionTypes.open]: navbarButtonUpdateTransition,\n      [viewTransitionTypes.close]: navbarButtonUpdateTransition,\n      [viewTransitionTypes.crossfade]: navbarButtonUpdateTransition,\n      default: 'none',\n    },\n  } as const satisfies Record<string, ViewTransitionClass>,\n  navbarButtonTooltip: {\n    update: {\n      [viewTransitionTypes['split-screen:open']]: 'none',\n      [viewTransitionTypes['split-screen:close']]: 'none',\n      [viewTransitionTypes.open]: 'auto',\n      [viewTransitionTypes.close]: 'auto',\n      default: 'none',\n    },\n  } as const satisfies Record<string, ViewTransitionClass>,\n  sidebar: {\n    enter: {\n      [viewTransitionTypes.open]: createViewTransitionType(\n        {new: {animationName: keyframes({from: {transform: 'translateX(100%)'}})}},\n        'panelSlideIn',\n      ),\n      default: 'none',\n    },\n    update: {\n      [viewTransitionTypes['split-screen:open']]: 'none',\n      [viewTransitionTypes['split-screen:close']]: 'none',\n      [viewTransitionTypes.crossfade]: 'auto',\n      default: 'none',\n    },\n    exit: {\n      [viewTransitionTypes.close]: createViewTransitionType(\n        {old: {animationName: keyframes({to: {transform: 'translateX(100%)'}})}},\n        'panelSlideOut',\n      ),\n      default: 'none',\n    },\n  } as const satisfies Record<string, ViewTransitionClass>,\n  splitscreen: {\n    enter: {\n      [viewTransitionTypes['split-screen:open']]: createViewTransitionType({\n        new: {animationName: splitScreenSlideIn},\n      }),\n      default: 'none',\n    },\n    update: {\n      [viewTransitionTypes.crossfade]: 'auto',\n      default: 'none',\n    },\n    exit: {\n      [viewTransitionTypes['split-screen:close']]: createViewTransitionType({\n        old: {animationName: splitScreenSlideOut},\n      }),\n      default: 'none',\n    },\n  } as const satisfies Record<string, ViewTransitionClass>,\n  studio: {\n    update: {\n      // [viewTransitionTypes.crossfade]: createViewTransitionType(\n      //   {\n      //     imagePair: {perspective: '1000px', transformStyle: 'preserve-3d'},\n      //     group: {animationDuration: '6s !important', animationTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1) !important', animationFillMode: 'both'},\n      //     old: {animationName: flipOut, backfaceVisibility: 'hidden', },\n      //     new: {animationName: flipIn, backfaceVisibility: 'hidden', }},\n      //   'crossfadeStudio',\n      // ),\n      [viewTransitionTypes['open']]: resizeStudioTransition,\n      [viewTransitionTypes['close']]: resizeStudioTransition,\n      [viewTransitionTypes['split-screen:open']]: splitStudioTransition,\n      [viewTransitionTypes['split-screen:close']]: splitStudioTransition,\n      [viewTransitionTypes.crossfade]: 'auto',\n      default: 'none',\n    },\n  } as const satisfies Record<string, ViewTransitionClass>,\n}\n\n/**\n * Default animation timings for all Themer view transitions\n */\nglobalStyle(\n  `:root:active-view-transition-type(${layoutTransitionType})::view-transition-group(*)`,\n  {animationDuration: '320ms', animationTimingFunction: 'cubic-bezier(0.65, 0, 0.35, 1)'},\n)\n\nglobalStyle(\n  [\n    `:root:active-view-transition-type(${viewTransitionTypes['split-screen:open']})::view-transition-group(*)`,\n    `:root:active-view-transition-type(${viewTransitionTypes['split-screen:close']})::view-transition-group(*)`,\n  ].join(','),\n  {animationDuration: '480ms'},\n)\n\n/** The layout's `Flex` positions the sidebar overlay on small screens */\nexport const layout = style({\n  position: 'relative',\n})\n\n/**\n * Disable animations automatically for themer view transitions if the user signals to do so\n */\nglobalStyle(\n  `:root:active-view-transition-type(${layoutTransitionType})::view-transition-group(*),:root:active-view-transition-type(${layoutTransitionType})::view-transition-old(*),:root:active-view-transition-type(${layoutTransitionType})::view-transition-new(*)`,\n  {\n    '@media': {\n      '(prefers-reduced-motion: reduce)': {\n        animation: 'none !important',\n      },\n    },\n  },\n)\n","import {addTransitionType} from 'react'\n\nimport {layoutTransitionType, viewTransitionTypes} from './ViewTransitions.css'\n\n/**\n * Adds the default sanity-themer transition type, which allows custom view transition overrides, as well as customization in userland\n */\nexport function addThemerTransitionType(type: keyof typeof viewTransitionTypes) {\n  if (!(type in viewTransitionTypes)) {\n    throw new Error(`Invalid transition type`, {cause: {type}})\n  }\n  addTransitionType(viewTransitionTypes[type])\n  // Used to mark that a themer transition is happening, can be styled with vanilla css, but also by setting class props on <ViewTransition>\n  addTransitionType(layoutTransitionType)\n}\n","import type {BuildThemeOptions} from '../theme/options'\nimport {presets} from '../theme/presets'\nimport type {ImagePalette} from './imagePalette'\n\n/**\n * Where a theme in the themer list comes from: the theme the Studio config\n * was generated from, one of the presets defined in code, or one the user\n * added in the tool. Only custom themes are editable — the others are\n * duplicated into a custom theme first.\n */\ntype ThemerThemeSource = 'config' | 'preset' | 'custom'\n\n/** A theme the themer tool lists @internal */\nexport interface ThemerTheme {\n  slug: string\n  title: string\n  options: BuildThemeOptions\n  source: ThemerThemeSource\n  /** The palette of the image the theme's colors were taken from, for custom themes */\n  palette?: ImagePalette\n}\n\n/** A theme the user added in the tool, as persisted @internal */\nexport interface CustomTheme {\n  slug: string\n  title: string\n  options: BuildThemeOptions\n  /** The palette of the image the theme's colors were taken from */\n  palette?: ImagePalette\n}\n\n/** The persisted themer state @internal */\nexport interface ThemerState {\n  /**\n   * The slug of the applied theme — `null` applies nothing on top of the\n   * Studio's configured theme\n   */\n  active: string | null\n  /** The themes the user added */\n  custom: CustomTheme[]\n  /** The slugs of the themes the user removed from the list */\n  removed: string[]\n  /**\n   * The slugs of the themes in the order the user arranged them — themes not\n   * in it (new presets, themes added since) follow in their default order\n   */\n  order: string[]\n}\n\n/** The slug of the theme the Studio config was generated from @internal */\nexport const CONFIG_SLUG = 'config'\n\n/** The title of the theme the Studio config was generated from */\nexport const CONFIG_TITLE = 'Studio config'\n\n/** The title new themes start out with @internal */\nexport const UNTITLED_THEME = 'Untitled theme'\n\n/** @internal */\nexport const initialThemerState: ThemerState = {active: null, custom: [], removed: [], order: []}\n\n/** The themes the tool works with, derived from the persisted state @internal */\nexport interface ResolvedThemes {\n  /** The themes to pick from, in list order */\n  themes: ThemerTheme[]\n  /** The removed themes, which can be restored */\n  removed: ThemerTheme[]\n  /** The applied theme */\n  active: ThemerTheme | undefined\n}\n\nconst presetsWithSource = presets.map((preset) =>\n  Object.assign({}, preset, {source: 'preset' as const}),\n)\n\n/**\n * Resolves the list of themes: the presets, then the user's own themes —\n * rearranged into the order the user dragged them into, with themes that\n * order does not know about kept in that default order after the ones it\n * does. Removed themes are set aside so they can be restored. The configured\n * theme is not in the list — `ThemeList` shows it ahead of it — and it is\n * what applies when no listed theme does: `active` is `undefined` for it, and\n * for an applied slug that no longer resolves.\n *\n * @internal\n */\nexport function resolveThemes(state: ThemerState): ResolvedThemes {\n  const all: ThemerTheme[] = [...presetsWithSource]\n\n  for (const theme of state.custom) {\n    all.push({\n      slug: theme.slug,\n      title: theme.title,\n      options: theme.options,\n      source: 'custom',\n      ...(theme.palette ? {palette: theme.palette} : {}),\n    })\n  }\n\n  const position = new Map(state.order.map((slug, index) => [slug, index]))\n  const rank = (theme: ThemerTheme) => position.get(theme.slug) ?? state.order.length\n\n  // A stable sort: the themes the order does not know about keep their default order\n  all.sort((a, b) => rank(a) - rank(b))\n\n  const removedSlugs = new Set(state.removed)\n  const themes = all.filter((theme) => !removedSlugs.has(theme.slug))\n  const removed = all.filter((theme) => removedSlugs.has(theme.slug))\n  const active = themes.find((theme) => theme.slug === state.active)\n\n  return {themes, removed, active}\n}\n\n/**\n * Creates a custom theme with a slug that cannot collide with the presets or\n * the configured theme.\n *\n * @internal\n */\nexport function createCustomTheme(\n  title: string,\n  options: BuildThemeOptions,\n  palette?: ImagePalette,\n): CustomTheme {\n  return {slug: `custom-${randomId()}`, title, options, ...(palette ? {palette} : {})}\n}\n\n/** The title of a duplicated theme @internal */\nexport function duplicateTitle(title: string): string {\n  return `${displayTitle(title)} copy`\n}\n\n/** The title to show for a theme, falling back when the user cleared it @internal */\nexport function displayTitle(title: string): string {\n  return title.trim() || UNTITLED_THEME\n}\n\nfunction randomId(): string {\n  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n    return crypto.randomUUID()\n  }\n\n  return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`\n}\n"],"mappings":";;;;;;AAKA,MAAa,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEE/B,SAAgB,wBAAwB,MAAwC;CAC9E,IAAI,EAAE,QAAQ,sBACZ,MAAU,MAAM,2BAA2B,EAAC,OAAO,EAAC,KAAI,EAAC,CAAC;CAI5D,AAFA,kBAAkB,oBAAoB,KAAK,GAE3C,kBAAkB,oBAAoB;AACxC;;ACoCA,MAAa,cAAc,UAGd,eAAe,iBAGf,iBAAiB,kBAGjB,qBAAkC;CAAC,QAAQ;CAAM,QAAQ,CAAC;CAAG,SAAS,CAAC;CAAG,OAAO,CAAC;AAAC,GAY1F,oBAAoB,QAAQ,KAAK,WACrC,OAAO,OAAO,CAAC,GAAG,QAAQ,EAAC,QAAQ,SAAiB,CAAC,CACvD;;;;;;;;;;;;AAaA,SAAgB,cAAc,OAAoC;CAChE,IAAM,MAAqB,CAAC,GAAG,iBAAiB;CAEhD,KAAK,IAAM,SAAS,MAAM,QACxB,IAAI,KAAK;EACP,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,SAAS,MAAM;EACf,QAAQ;EACR,GAAI,MAAM,UAAU,EAAC,SAAS,MAAM,QAAO,IAAI,CAAC;CAClD,CAAC;CAGH,IAAM,WAAW,IAAI,IAAI,MAAM,MAAM,KAAK,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,GAClE,QAAQ,UAAuB,SAAS,IAAI,MAAM,IAAI,KAAK,MAAM,MAAM;CAG7E,IAAI,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;CAEpC,IAAM,eAAe,IAAI,IAAI,MAAM,OAAO,GACpC,SAAS,IAAI,QAAQ,UAAU,CAAC,aAAa,IAAI,MAAM,IAAI,CAAC;CAIlE,OAAO;EAAC;EAAQ,SAHA,IAAI,QAAQ,UAAU,aAAa,IAAI,MAAM,IAAI,CAGjD;EAAS,QAFV,OAAO,MAAM,UAAU,MAAM,SAAS,MAAM,MAElC;CAAM;AACjC;;;;;;;AAQA,SAAgB,kBACd,OACA,SACA,SACa;CACb,OAAO;EAAC,MAAM,UAAU,SAAS;EAAK;EAAO;EAAS,GAAI,UAAU,EAAC,QAAO,IAAI,CAAC;CAAE;AACrF;;AAGA,SAAgB,eAAe,OAAuB;CACpD,OAAO,GAAG,aAAa,KAAK,EAAE;AAChC;;AAGA,SAAgB,aAAa,OAAuB;CAClD,OAAO,MAAM,KAAK,KAAA;AACpB;AAEA,SAAS,WAAmB;CAK1B,OAJI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,aACzD,OAAO,WAAW,IAGpB,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,EAAE;AAC5E"}
\ No newline at end of file