@jobber/components 6.86.5 → 6.88.0

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.
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
2
  import type { AtlantisThemeContextProviderProps, AtlantisThemeContextValue } from "./types";
3
3
  export declare const atlantisThemeContextDefaultValues: AtlantisThemeContextValue;
4
- export declare function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, }: AtlantisThemeContextProviderProps): React.JSX.Element;
4
+ export declare function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, dangerouslyOverrideTokens, }: AtlantisThemeContextProviderProps): React.JSX.Element;
5
5
  export declare function useAtlantisTheme(): AtlantisThemeContextValue;
@@ -9,6 +9,10 @@ export interface AtlantisThemeContextValue {
9
9
  * The design tokens for the current theme.
10
10
  */
11
11
  readonly tokens: typeof tokens;
12
+ /**
13
+ * Any overridden tokens supplied by the user.
14
+ */
15
+ readonly overrideTokens?: OverrideTokens;
12
16
  }
13
17
  export interface AtlantisThemeContextProviderProps extends PropsWithChildren {
14
18
  /**
@@ -20,7 +24,20 @@ export interface AtlantisThemeContextProviderProps extends PropsWithChildren {
20
24
  * This is dangerous because the children in this provider will not be able to change the theme.
21
25
  */
22
26
  readonly dangerouslyOverrideTheme?: Theme;
27
+ /**
28
+ * Overrides existing design tokens with custom values. Can also supply custom tokens which will be accessible
29
+ * via useAtlantisTheme() context and css variables.
30
+ * If provided, these tokens will be used for both light and dark themes.
31
+ *
32
+ * **Important**: you should provide a constant or at least a memoized value for performance reasons.
33
+ */
34
+ readonly dangerouslyOverrideTokens?: OverrideTokens;
23
35
  }
36
+ export type OverrideTokens = {
37
+ [K in keyof typeof tokens]?: (typeof tokens)[K];
38
+ } & {
39
+ [customKey: string]: string | number;
40
+ };
24
41
  export type Theme = "light" | "dark";
25
42
  export interface ThemeChangeDetails {
26
43
  theme: Theme;
@@ -342,7 +342,7 @@ var merge$1 = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(merge_1);
342
342
 
343
343
  const THEME_CHANGE_EVENT = "atlantis.toggle-theme";
344
344
 
345
- var styles = {"staticThemeProviderWrapper":"P6HrDSaI0Ac-","spinning":"iq03qkKnXBA-"};
345
+ var styles = {"staticThemeProviderWrapper":"P6HrDSaI0Ac-","overrideTokensWrapper":"j-NMCOBL3-E-","spinning":"iq03qkKnXBA-"};
346
346
 
347
347
  const atlantisThemeContextDefaultValues = {
348
348
  theme: "light",
@@ -350,17 +350,17 @@ const atlantisThemeContextDefaultValues = {
350
350
  };
351
351
  const actualDarkTokens = merge$1({}, design.tokens, design.darkTokens);
352
352
  const AtlantisThemeContext = React.createContext(atlantisThemeContextDefaultValues);
353
- function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, }) {
353
+ function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, dangerouslyOverrideTokens, }) {
354
354
  if (dangerouslyOverrideTheme) {
355
- return (React.createElement(InternalStaticThemeProvider, { dangerouslyOverrideTheme: dangerouslyOverrideTheme }, children));
355
+ return (React.createElement(InternalStaticThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens, dangerouslyOverrideTheme: dangerouslyOverrideTheme }, children));
356
356
  }
357
- return (React.createElement(InternalDynamicThemeProvider, null, children));
357
+ return (React.createElement(InternalDynamicThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens }, children));
358
358
  }
359
- function InternalDynamicThemeProvider({ children }) {
359
+ function InternalDynamicThemeProvider({ children, dangerouslyOverrideTokens, }) {
360
360
  var _a;
361
361
  const initialTheme = (_a = globalThis.document.documentElement.dataset.theme) !== null && _a !== void 0 ? _a : "light";
362
362
  const [internalTheme, setInternalTheme] = React.useState(initialTheme);
363
- const currentTokens = internalTheme === "dark" ? actualDarkTokens : design.tokens;
363
+ const { finalTokens, cssVariableOverrides } = useTokens(internalTheme, dangerouslyOverrideTokens);
364
364
  const handleThemeChangeEvent = React.useCallback((event) => {
365
365
  const newTheme = event.detail.theme;
366
366
  setInternalTheme(newTheme);
@@ -375,20 +375,46 @@ function InternalDynamicThemeProvider({ children }) {
375
375
  }, [handleThemeChangeEvent]);
376
376
  return (React.createElement(AtlantisThemeContext.Provider, { value: {
377
377
  theme: internalTheme,
378
- tokens: currentTokens,
379
- } }, children));
378
+ tokens: finalTokens,
379
+ overrideTokens: dangerouslyOverrideTokens,
380
+ } }, cssVariableOverrides ? (React.createElement("div", { className: styles.overrideTokensWrapper, style: cssVariableOverrides }, children)) : (children)));
380
381
  }
381
- function InternalStaticThemeProvider({ dangerouslyOverrideTheme, children, }) {
382
- const currentTokens = dangerouslyOverrideTheme === "dark" ? actualDarkTokens : design.tokens;
382
+ function InternalStaticThemeProvider({ dangerouslyOverrideTheme, children, dangerouslyOverrideTokens, }) {
383
+ const { finalTokens, cssVariableOverrides } = useTokens(dangerouslyOverrideTheme, dangerouslyOverrideTokens);
383
384
  return (React.createElement(AtlantisThemeContext.Provider, { value: {
384
385
  theme: dangerouslyOverrideTheme,
385
- tokens: currentTokens,
386
+ tokens: finalTokens,
387
+ overrideTokens: dangerouslyOverrideTokens,
386
388
  } },
387
- React.createElement("div", { "data-theme": dangerouslyOverrideTheme, className: styles.staticThemeProviderWrapper }, children)));
389
+ React.createElement("div", { "data-theme": dangerouslyOverrideTheme, className: styles.staticThemeProviderWrapper, style: cssVariableOverrides }, children)));
388
390
  }
389
391
  function useAtlantisTheme() {
390
392
  return React.useContext(AtlantisThemeContext);
391
393
  }
394
+ function getCssVariableOverrides(overrideTokens) {
395
+ const cssVariables = Object.entries(overrideTokens).reduce((variables, [tokenName, tokenValue]) => {
396
+ // @ts-expect-error - css variables are valid keys for style objects. @types/react may be outdated.
397
+ variables[`--${tokenName}`] = tokenValue;
398
+ return variables;
399
+ }, {});
400
+ return cssVariables;
401
+ }
402
+ function useTokens(theme, overrideTokens) {
403
+ const currentTokens = theme === "dark" ? actualDarkTokens : design.tokens;
404
+ const finalTokens = React.useMemo(() => {
405
+ if (overrideTokens) {
406
+ return merge$1({}, currentTokens, overrideTokens);
407
+ }
408
+ return currentTokens;
409
+ }, [currentTokens, overrideTokens]);
410
+ const cssVariableOverrides = overrideTokens
411
+ ? getCssVariableOverrides(overrideTokens)
412
+ : undefined;
413
+ return {
414
+ finalTokens,
415
+ cssVariableOverrides,
416
+ };
417
+ }
392
418
 
393
419
  exports.AtlantisThemeContextProvider = AtlantisThemeContextProvider;
394
420
  exports.THEME_CHANGE_EVENT = THEME_CHANGE_EVENT;
@@ -1,5 +1,5 @@
1
1
  import { tokens, darkTokens } from '@jobber/design';
2
- import React__default, { createContext, useState, useCallback, useEffect, useContext } from 'react';
2
+ import React__default, { createContext, useState, useCallback, useEffect, useContext, useMemo } from 'react';
3
3
  import { g as getDefaultExportFromCjs } from './_commonjsHelpers-es.js';
4
4
  import { e as eq_1, c as _Stack } from './identity-es.js';
5
5
  import { _ as _baseAssignValue } from './_baseAssignValue-es.js';
@@ -340,7 +340,7 @@ var merge$1 = /*@__PURE__*/getDefaultExportFromCjs(merge_1);
340
340
 
341
341
  const THEME_CHANGE_EVENT = "atlantis.toggle-theme";
342
342
 
343
- var styles = {"staticThemeProviderWrapper":"P6HrDSaI0Ac-","spinning":"iq03qkKnXBA-"};
343
+ var styles = {"staticThemeProviderWrapper":"P6HrDSaI0Ac-","overrideTokensWrapper":"j-NMCOBL3-E-","spinning":"iq03qkKnXBA-"};
344
344
 
345
345
  const atlantisThemeContextDefaultValues = {
346
346
  theme: "light",
@@ -348,17 +348,17 @@ const atlantisThemeContextDefaultValues = {
348
348
  };
349
349
  const actualDarkTokens = merge$1({}, tokens, darkTokens);
350
350
  const AtlantisThemeContext = createContext(atlantisThemeContextDefaultValues);
351
- function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, }) {
351
+ function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, dangerouslyOverrideTokens, }) {
352
352
  if (dangerouslyOverrideTheme) {
353
- return (React__default.createElement(InternalStaticThemeProvider, { dangerouslyOverrideTheme: dangerouslyOverrideTheme }, children));
353
+ return (React__default.createElement(InternalStaticThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens, dangerouslyOverrideTheme: dangerouslyOverrideTheme }, children));
354
354
  }
355
- return (React__default.createElement(InternalDynamicThemeProvider, null, children));
355
+ return (React__default.createElement(InternalDynamicThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens }, children));
356
356
  }
357
- function InternalDynamicThemeProvider({ children }) {
357
+ function InternalDynamicThemeProvider({ children, dangerouslyOverrideTokens, }) {
358
358
  var _a;
359
359
  const initialTheme = (_a = globalThis.document.documentElement.dataset.theme) !== null && _a !== void 0 ? _a : "light";
360
360
  const [internalTheme, setInternalTheme] = useState(initialTheme);
361
- const currentTokens = internalTheme === "dark" ? actualDarkTokens : tokens;
361
+ const { finalTokens, cssVariableOverrides } = useTokens(internalTheme, dangerouslyOverrideTokens);
362
362
  const handleThemeChangeEvent = useCallback((event) => {
363
363
  const newTheme = event.detail.theme;
364
364
  setInternalTheme(newTheme);
@@ -373,19 +373,45 @@ function InternalDynamicThemeProvider({ children }) {
373
373
  }, [handleThemeChangeEvent]);
374
374
  return (React__default.createElement(AtlantisThemeContext.Provider, { value: {
375
375
  theme: internalTheme,
376
- tokens: currentTokens,
377
- } }, children));
376
+ tokens: finalTokens,
377
+ overrideTokens: dangerouslyOverrideTokens,
378
+ } }, cssVariableOverrides ? (React__default.createElement("div", { className: styles.overrideTokensWrapper, style: cssVariableOverrides }, children)) : (children)));
378
379
  }
379
- function InternalStaticThemeProvider({ dangerouslyOverrideTheme, children, }) {
380
- const currentTokens = dangerouslyOverrideTheme === "dark" ? actualDarkTokens : tokens;
380
+ function InternalStaticThemeProvider({ dangerouslyOverrideTheme, children, dangerouslyOverrideTokens, }) {
381
+ const { finalTokens, cssVariableOverrides } = useTokens(dangerouslyOverrideTheme, dangerouslyOverrideTokens);
381
382
  return (React__default.createElement(AtlantisThemeContext.Provider, { value: {
382
383
  theme: dangerouslyOverrideTheme,
383
- tokens: currentTokens,
384
+ tokens: finalTokens,
385
+ overrideTokens: dangerouslyOverrideTokens,
384
386
  } },
385
- React__default.createElement("div", { "data-theme": dangerouslyOverrideTheme, className: styles.staticThemeProviderWrapper }, children)));
387
+ React__default.createElement("div", { "data-theme": dangerouslyOverrideTheme, className: styles.staticThemeProviderWrapper, style: cssVariableOverrides }, children)));
386
388
  }
387
389
  function useAtlantisTheme() {
388
390
  return useContext(AtlantisThemeContext);
389
391
  }
392
+ function getCssVariableOverrides(overrideTokens) {
393
+ const cssVariables = Object.entries(overrideTokens).reduce((variables, [tokenName, tokenValue]) => {
394
+ // @ts-expect-error - css variables are valid keys for style objects. @types/react may be outdated.
395
+ variables[`--${tokenName}`] = tokenValue;
396
+ return variables;
397
+ }, {});
398
+ return cssVariables;
399
+ }
400
+ function useTokens(theme, overrideTokens) {
401
+ const currentTokens = theme === "dark" ? actualDarkTokens : tokens;
402
+ const finalTokens = useMemo(() => {
403
+ if (overrideTokens) {
404
+ return merge$1({}, currentTokens, overrideTokens);
405
+ }
406
+ return currentTokens;
407
+ }, [currentTokens, overrideTokens]);
408
+ const cssVariableOverrides = overrideTokens
409
+ ? getCssVariableOverrides(overrideTokens)
410
+ : undefined;
411
+ return {
412
+ finalTokens,
413
+ cssVariableOverrides,
414
+ };
415
+ }
390
416
 
391
417
  export { AtlantisThemeContextProvider as A, THEME_CHANGE_EVENT as T, atlantisThemeContextDefaultValues as a, useAtlantisTheme as u };
@@ -109,8 +109,10 @@ export interface ComboboxOptionProps {
109
109
  * Advanced: A custom render prop to completely control how this option is rendered.
110
110
  * The function receives the option's props, and a boolean indicating if the option is selected.
111
111
  */
112
- readonly customRender?: (option: Omit<ComboboxOptionProps, "customRender"> & {
112
+ readonly customRender?: (option: Pick<ComboboxOptionProps, "id" | "label" | "prefix"> & {
113
113
  isSelected: boolean;
114
+ /** Render the default option content. */
115
+ defaultContent: ReactElement;
114
116
  }) => React.ReactNode;
115
117
  /**
116
118
  * Callback function invoked when the option is clicked.
@@ -18,7 +18,7 @@ function ComboboxOption(props) {
18
18
  selectionHandler === null || selectionHandler === void 0 ? void 0 : selectionHandler({ id, label });
19
19
  onClick === null || onClick === void 0 ? void 0 : onClick({ id, label });
20
20
  };
21
- return (React.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
21
+ return (React.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected, defaultContent: (React.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected }))) }))) : (React.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
22
22
  }
23
23
  function InternalDefaultContent(props) {
24
24
  return (React.createElement(React.Fragment, null,
@@ -16,7 +16,7 @@ function ComboboxOption(props) {
16
16
  selectionHandler === null || selectionHandler === void 0 ? void 0 : selectionHandler({ id, label });
17
17
  onClick === null || onClick === void 0 ? void 0 : onClick({ id, label });
18
18
  };
19
- return (React__default.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React__default.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
19
+ return (React__default.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected, defaultContent: (React__default.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected }))) }))) : (React__default.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
20
20
  }
21
21
  function InternalDefaultContent(props) {
22
22
  return (React__default.createElement(React__default.Fragment, null,
package/dist/styles.css CHANGED
@@ -2,6 +2,10 @@
2
2
  display: contents;
3
3
  }
4
4
 
5
+ .j-NMCOBL3-E- {
6
+ display: contents;
7
+ }
8
+
5
9
  ._37kZB-nYE08- {
6
10
  display: -ms-flexbox;
7
11
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.86.5",
3
+ "version": "6.88.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -543,5 +543,5 @@
543
543
  "> 1%",
544
544
  "IE 10"
545
545
  ],
546
- "gitHead": "69bf4a19f39dc779173c705accb66f3514f80604"
546
+ "gitHead": "b315d894eb1d6f8ea122c880c0338234c860404a"
547
547
  }