@focus4/styling 11.13.0 → 11.15.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.
- package/lib/focus4.styling.css +24 -16
- package/lib/focus4.styling.d.ts +2 -2
- package/lib/focus4.styling.js +76 -19
- package/lib/focus4.styling.js.map +1 -1
- package/lib/theme/common.d.ts +4 -3
- package/lib/theme/index.d.ts +2 -1
- package/lib/theme/theme-provider.d.ts +71 -0
- package/lib/theme/themr.d.ts +1 -1
- package/lib/theme/to-bem.d.ts +29 -0
- package/lib/theme/use-theme.d.ts +9 -1
- package/lib/utils/color-scheme.d.ts +5 -0
- package/lib/utils/index.d.ts +0 -1
- package/package.json +6 -6
- package/lib/utils/get-icon.d.ts +0 -12
package/lib/focus4.styling.css
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
:root {
|
|
2
|
+
--color-black: 0, 0, 0;
|
|
3
|
+
--color-white: 255, 255, 255;
|
|
4
|
+
|
|
2
5
|
--palette-red-50: 255, 235, 238;
|
|
3
6
|
--palette-red-100: 255, 205, 210;
|
|
4
7
|
--palette-red-200: 239, 154, 154;
|
|
@@ -271,9 +274,22 @@
|
|
|
271
274
|
--palette-blue-grey-700: 69, 90, 100;
|
|
272
275
|
--palette-blue-grey-800: 55, 71, 79;
|
|
273
276
|
--palette-blue-grey-900: 38, 50, 56;
|
|
277
|
+
}
|
|
274
278
|
|
|
275
|
-
|
|
276
|
-
--color-
|
|
279
|
+
:root[dark] {
|
|
280
|
+
--color-black: 238, 238, 238;
|
|
281
|
+
--color-white: 11, 11, 11;
|
|
282
|
+
|
|
283
|
+
--palette-grey-50: 22, 22, 22;
|
|
284
|
+
--palette-grey-100: 33, 33, 33;
|
|
285
|
+
--palette-grey-200: 44, 44, 44;
|
|
286
|
+
--palette-grey-300: 66, 66, 66;
|
|
287
|
+
--palette-grey-400: 97, 97, 97;
|
|
288
|
+
--palette-grey-500: 117, 117, 117;
|
|
289
|
+
--palette-grey-600: 158, 158, 158;
|
|
290
|
+
--palette-grey-700: 189, 189, 189;
|
|
291
|
+
--palette-grey-800: 224, 224, 224;
|
|
292
|
+
--palette-grey-900: 238, 238, 238;
|
|
277
293
|
}
|
|
278
294
|
|
|
279
295
|
:root {
|
|
@@ -310,21 +326,9 @@
|
|
|
310
326
|
:root[dark] {
|
|
311
327
|
color-scheme: dark;
|
|
312
328
|
|
|
313
|
-
--color-white: 11, 11, 11;
|
|
314
|
-
--color-black: 238, 238, 238;
|
|
315
329
|
--color-primary: var(--palette-indigo-300);
|
|
316
|
-
--color-primary-light: var(--palette-indigo-
|
|
317
|
-
|
|
318
|
-
--palette-grey-50: 22, 22, 22;
|
|
319
|
-
--palette-grey-100: 33, 33, 33;
|
|
320
|
-
--palette-grey-200: 44, 44, 44;
|
|
321
|
-
--palette-grey-300: 66, 66, 66;
|
|
322
|
-
--palette-grey-400: 97, 97, 97;
|
|
323
|
-
--palette-grey-500: 117, 117, 117;
|
|
324
|
-
--palette-grey-600: 158, 158, 158;
|
|
325
|
-
--palette-grey-700: 189, 189, 189;
|
|
326
|
-
--palette-grey-800: 224, 224, 224;
|
|
327
|
-
--palette-grey-900: 238, 238, 238;
|
|
330
|
+
--color-primary-light: var(--palette-indigo-900);
|
|
331
|
+
--color-accent: var(--palette-pink-a100);
|
|
328
332
|
}
|
|
329
333
|
|
|
330
334
|
html {
|
|
@@ -388,3 +392,7 @@ h6 {
|
|
|
388
392
|
line-height: 24px;
|
|
389
393
|
letter-spacing: 0.04em;
|
|
390
394
|
}
|
|
395
|
+
|
|
396
|
+
th {
|
|
397
|
+
font-weight: normal;
|
|
398
|
+
}
|
package/lib/focus4.styling.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "./variables";
|
|
2
2
|
import "./global.css";
|
|
3
|
-
export { PanelDescriptor, ScrollableContext, ScrollspyContext, colorScheme, cssTransitionProps, getDefaultTransition,
|
|
4
|
-
export { CSSContext, CSSElement, CSSMod, CSSProp, CSSToStrings, ThemeContext, ToBem, fromBem, themr, toBem, useTheme } from "./theme";
|
|
3
|
+
export { PanelDescriptor, ScrollableContext, ScrollspyContext, colorScheme, cssTransitionProps, getDefaultTransition, initColorScheme, getSpringTransition } from "./utils";
|
|
4
|
+
export { CSSContext, CSSElement, CSSMod, CSSProp, CSSTheme, CSSToStrings, FocusCSSContext, ThemeContext, ThemeProvider, ThemeProviderProps, ToBem, fromBem, themr, toBem, useTheme } from "./theme";
|
package/lib/focus4.styling.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
1
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
2
2
|
import { observable, autorun } from 'mobx';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
|
-
import
|
|
4
|
+
import { themeable } from '@focus4/core';
|
|
5
5
|
import classNames from 'classnames';
|
|
6
6
|
import { pick, upperFirst } from 'lodash';
|
|
7
7
|
import { useObserver } from 'mobx-react';
|
|
8
|
-
import { themeable } from '@focus4/core';
|
|
9
8
|
|
|
10
9
|
function get() {
|
|
11
10
|
const { animationDelay, animationDuration, animationTimingFunction } = window.getComputedStyle(document.body);
|
|
@@ -52,20 +51,12 @@ function toMs(d) {
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
function getIcon(name, isCustom) {
|
|
56
|
-
if (isCustom === undefined) {
|
|
57
|
-
isCustom = i18next.t(`${name}.library`) !== "material";
|
|
58
|
-
name = i18next.t(`${name}.name`);
|
|
59
|
-
}
|
|
60
|
-
if (isCustom) {
|
|
61
|
-
return jsx("span", { className: `icon-${name}` });
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
return name;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
54
|
const colorScheme = observable({ dark: false });
|
|
55
|
+
/**
|
|
56
|
+
* Permet d'initialiser l'utilisation du mode sombre dans une application Focus. Par défaut, il est initialisé avec le thème du navigateur de
|
|
57
|
+
* l'utilisateur.
|
|
58
|
+
* @param disableAutoDarkMode Désactive la prise en compte du thème de l'utilisateur et initialise toujours en thème clair.
|
|
59
|
+
*/
|
|
69
60
|
function initColorScheme(disableAutoDarkMode = false) {
|
|
70
61
|
const ls = localStorage.getItem("color-scheme");
|
|
71
62
|
if (ls === "dark" || (!ls && !disableAutoDarkMode && window.matchMedia?.("(prefers-color-scheme: dark)").matches)) {
|
|
@@ -102,6 +93,31 @@ const ScrollspyContext = createContext({
|
|
|
102
93
|
|
|
103
94
|
const ThemeContext = createContext({});
|
|
104
95
|
|
|
96
|
+
/**
|
|
97
|
+
* `toBem` permet de transformer un objet de classes CSS, tel que celui importé d'un module CSS, dont les noms respectent la convention BEM
|
|
98
|
+
* en un objet contenant une fonction par "élément" à laquelle on peut appliquer ses "modificateurs".
|
|
99
|
+
*
|
|
100
|
+
* Par exemple, un objet contenant les classes
|
|
101
|
+
* ```ts
|
|
102
|
+
* ["panel", "panel--editing", "panel--loading", "title", "title--top", "title--bottom"]
|
|
103
|
+
* ```
|
|
104
|
+
* sera transformé en un objet avec 2 fonctions `panel` et `title` :
|
|
105
|
+
* ```ts
|
|
106
|
+
* {
|
|
107
|
+
* panel({editing?: boolean; loading?: boolean}) => string;
|
|
108
|
+
* title({top?: boolean; bottom?: boolean}) => string;
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
* Un appel à une fonction retournera la classe CSS de l'"élément", à laquelle seront ajoutées ou non les classes des différents "modificateurs",
|
|
112
|
+
* selon les valeurs des différents booléens.
|
|
113
|
+
*
|
|
114
|
+
* Vous pouvez utiliser `toBem` pour éviter d'avoir à concaténer des classes CSS à la main et pour rendre vos composants et votre CSS plus propres.
|
|
115
|
+
* Son usage est bien évidemment totalement facultatif et à utiliser si cela vous arrange.
|
|
116
|
+
*
|
|
117
|
+
* _Remarque 1 : Les modules CSS importés doivent avoir des définitions Typescript générés par la commande `focus4 cssgen` du module `@focus4/tooling`._
|
|
118
|
+
*
|
|
119
|
+
* _Remarque 2 : Les propriétés `theme` des différents composants Focus acceptent aussi bien un objet CSS classique ou un objet créé par `toBem`._
|
|
120
|
+
*/
|
|
105
121
|
function toBem(css) {
|
|
106
122
|
const data = {};
|
|
107
123
|
for (const key in css) {
|
|
@@ -125,6 +141,10 @@ function toBem(css) {
|
|
|
125
141
|
}
|
|
126
142
|
}), {});
|
|
127
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* `fromBem` permet de faire la transformation inverse de `toBem`, à savoir prendre l'objet résultant d'un appel à `toBem` et de ressortir un objet
|
|
146
|
+
* qui contient toutes les classes CSS qui le compose.
|
|
147
|
+
*/
|
|
128
148
|
function fromBem(css) {
|
|
129
149
|
const res = {};
|
|
130
150
|
for (const key in css) {
|
|
@@ -141,14 +161,51 @@ function fromBem(css) {
|
|
|
141
161
|
return res;
|
|
142
162
|
}
|
|
143
163
|
|
|
144
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Le `ThemeProvider` permet d'ajouter des classes CSS aux composants Focus (et autres composants utilisant `useTheme`) posés
|
|
166
|
+
* à l'intérieur (via un context React).
|
|
167
|
+
*
|
|
168
|
+
* Les classes CSS ajoutées dans un `ThemeProvider` s'ajouteront aux éventuelles classes posées par un `ThemeProvider` parent,
|
|
169
|
+
* y compris sur les mêmes composants.
|
|
170
|
+
*/
|
|
171
|
+
function ThemeProvider({ appTheme, children }) {
|
|
172
|
+
const context = useContext(ThemeContext);
|
|
173
|
+
const mergedContext = useMemo(() => {
|
|
174
|
+
const mc = {};
|
|
175
|
+
for (const key in context) {
|
|
176
|
+
if (key in appTheme && appTheme[key]) {
|
|
177
|
+
mc[key] = themeable(fromBem(context[key]), fromBem(appTheme[key]));
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
mc[key] = context[key];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
for (const key in appTheme) {
|
|
184
|
+
if (!(key in context) && appTheme[key]) {
|
|
185
|
+
mc[key] = appTheme[key];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return mc;
|
|
189
|
+
}, [appTheme, context]);
|
|
190
|
+
return jsx(ThemeContext.Provider, { value: mergedContext, children: children });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* `useTheme` permet de récupérer les classes CSS passées dans un éventuel `ThemeProvider` parent et de les fusionner avec d'autres classes CSS
|
|
195
|
+
* passées en paramètre.
|
|
196
|
+
*
|
|
197
|
+
* `useTheme` accepte aussi bien des objets de classes CSS classiques (importés d'un module CSS), que des objets créés avec `toBem`.
|
|
198
|
+
*
|
|
199
|
+
* @param name L'identifiant du composant dans le `appTheme` du `ThemeProvider`
|
|
200
|
+
* @param themes Les objets de classes CSS à fusionner ensemble et avec celui du contexte.
|
|
201
|
+
*/
|
|
145
202
|
function useTheme(name, ...themes) {
|
|
146
203
|
const contextTheme = fromBem(useContext(ThemeContext)[name]) || {};
|
|
147
204
|
return toBem(themeable(contextTheme, ...themes.filter(x => x).map(x => fromBem(x))));
|
|
148
205
|
}
|
|
149
206
|
|
|
150
207
|
/**
|
|
151
|
-
*
|
|
208
|
+
* Permet de créer un composant wrapper pour utiliser `useTheme` dans le `render()` d'un composant classe.
|
|
152
209
|
* @param name Le nom de la clé de theme.
|
|
153
210
|
* @param localTheme Le theme local, fourni par le composant.
|
|
154
211
|
*/
|
|
@@ -161,5 +218,5 @@ function themr(name, localTheme) {
|
|
|
161
218
|
return TC;
|
|
162
219
|
}
|
|
163
220
|
|
|
164
|
-
export { ScrollableContext, ScrollspyContext, ThemeContext, colorScheme, cssTransitionProps, fromBem, getDefaultTransition,
|
|
221
|
+
export { ScrollableContext, ScrollspyContext, ThemeContext, ThemeProvider, colorScheme, cssTransitionProps, fromBem, getDefaultTransition, getSpringTransition, initColorScheme, themr, toBem, useTheme };
|
|
165
222
|
//# sourceMappingURL=focus4.styling.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus4.styling.js","sources":["../src/utils/animation.ts","../src/utils/get-icon.tsx","../src/utils/color-scheme.ts","../src/utils/scroll-contexts.ts","../src/theme/common.ts","../src/theme/to-bem.ts","../src/theme/use-theme.ts","../src/theme/themr.tsx"],"sourcesContent":["function get() {\r\n const {animationDelay, animationDuration, animationTimingFunction} = window.getComputedStyle(document.body);\r\n\r\n const delay = toMs(animationDelay);\r\n const duration = toMs(animationDuration);\r\n const ease = animationTimingFunction.startsWith(\"cubic-bezier\")\r\n ? animationTimingFunction.substring(13).split(\",\").map(parseFloat)\r\n : undefined;\r\n\r\n return {delay, duration, ease};\r\n}\r\n\r\nexport function getDefaultTransition() {\r\n const {delay, duration, ease} = get();\r\n return {\r\n delay: delay / 1000,\r\n duration: duration / 1000,\r\n ease\r\n } as const;\r\n}\r\n\r\nexport function getSpringTransition() {\r\n return {\r\n type: \"spring\",\r\n bounce: 0,\r\n duration: get().duration / 1000\r\n } as const;\r\n}\r\n\r\nexport function cssTransitionProps({\r\n enter,\r\n enterActive,\r\n exit,\r\n exitActive\r\n}: {\r\n enter: string;\r\n enterActive: string;\r\n exit: string;\r\n exitActive: string;\r\n}) {\r\n const {delay, duration} = get();\r\n return {\r\n timeout: delay + duration,\r\n classNames: {\r\n enter,\r\n enterActive,\r\n exit,\r\n exitActive\r\n }\r\n };\r\n}\r\n\r\nfunction toMs(d: string) {\r\n if (d.endsWith(\"ms\")) {\r\n return +d.substring(0, d.length - 2);\r\n } else {\r\n return +d.substring(0, d.length - 1) * 1000;\r\n }\r\n}\r\n","import i18next from \"i18next\";\r\nimport {ReactNode} from \"react\";\r\n\r\n/**\r\n * Récupère l'icône correspondante au nom.\r\n * @param name Le nom de l'icône.\r\n * @param isCustom Icône custom ou non.\r\n */\r\nexport function getIcon(name: ReactNode, isCustom: boolean): JSX.Element | string;\r\n/**\r\n * Récupère l'icône par sa clé i18n.\r\n * @param i18nKey La clé i18n de l'icône.\r\n */\r\nexport function getIcon(i18nKey: string): JSX.Element | string;\r\nexport function getIcon(name?: ReactNode, isCustom?: boolean) {\r\n if (isCustom === undefined) {\r\n isCustom = i18next.t(`${name as string}.library`) !== \"material\";\r\n name = i18next.t(`${name as string}.name`);\r\n }\r\n\r\n if (isCustom) {\r\n return <span className={`icon-${name as string}`} />;\r\n } else {\r\n return name;\r\n }\r\n}\r\n","import {autorun, observable} from \"mobx\";\r\n\r\nexport const colorScheme = observable({dark: false});\r\n\r\nexport function initColorScheme(disableAutoDarkMode = false) {\r\n const ls = localStorage.getItem(\"color-scheme\");\r\n if (ls === \"dark\" || (!ls && !disableAutoDarkMode && window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches)) {\r\n colorScheme.dark = true;\r\n }\r\n localStorage.setItem(\"color-scheme\", colorScheme.dark ? \"dark\" : \"light\");\r\n\r\n autorun(() => {\r\n const darkModeAttribute = document.documentElement.hasAttribute(\"dark\");\r\n if (colorScheme.dark && !darkModeAttribute) {\r\n document.documentElement.setAttribute(\"dark\", \"true\");\r\n localStorage.setItem(\"color-scheme\", \"dark\");\r\n } else if (!colorScheme.dark && darkModeAttribute) {\r\n document.documentElement.removeAttribute(\"dark\");\r\n localStorage.setItem(\"color-scheme\", \"light\");\r\n }\r\n });\r\n}\r\n","import {createContext, HTMLProps, ReactPortal} from \"react\";\r\n\r\nexport interface PanelDescriptor {\r\n node: HTMLDivElement;\r\n title?: string;\r\n}\r\n\r\n/** Contexte d'un Scrollable, expose les méthodes associées. */\r\nexport const ScrollableContext = createContext<{\r\n /**\r\n * Retourne la status du header.\r\n * @returns La taille du header et s'il est sticky ou non.\r\n */\r\n getHeaderStatus(): {sticky: boolean; height: number};\r\n /**\r\n * Affiche un élement dans le menu sticky du Scrollable\r\n * @param node Le noeud React.\r\n * @param parentNode Noeud à suivre pour positionner l'élément sticky.\r\n * @param retractable Menu rétractable.\r\n * @returns Le Portal associé.\r\n */\r\n menu(node: JSX.Element, parentNode: HTMLElement | null, retractable: boolean): ReactPortal | null;\r\n /**\r\n * Affiche un élement dans le Scrollable.\r\n * @param node Le noeud React.\r\n * @returns Le Portal associé.\r\n */\r\n portal(node: JSX.Element): ReactPortal;\r\n /**\r\n * Enregistre le header dans le Scrollable\r\n * @param nonStickyElement Le noeud DOM représentant le header non sticky.\r\n * @param canDeploy Précise si le header est toujours sticky ou non.\r\n * @returns Le disposer.\r\n */\r\n registerHeader(nonStickyElement: HTMLElement, canDeploy: boolean): () => void;\r\n /**\r\n * Set les props du header du Scrollable.\r\n * @param headerProps Les props du header.\r\n * @returns Le disposer.\r\n */\r\n registerHeaderProps(headerProps: HTMLProps<HTMLElement>): void;\r\n /**\r\n * Enregistre un observateur d'intersection avec le viewport du Scrollable.\r\n * @param node Le noeud DOM à observer.\r\n * @param onIntersect Le callback à appeler lors d'une intersection.\r\n * @returns Le disposer.\r\n */\r\n registerIntersect(node: HTMLElement, onIntersect: (ratio: number, isIntersecting: boolean) => void): () => void;\r\n /**\r\n * Scrolle vers la position demandée.\r\n * @param options Options.\r\n */\r\n scrollTo(options?: ScrollToOptions): void;\r\n}>({} as any);\r\n\r\n/** Contexte d'un ScrollspyContainer, expose les méthodes associées. */\r\nexport const ScrollspyContext = createContext({\r\n /**\r\n * Enregistre un panel dans le Scrollspu\r\n * @param name L'id du panel souhaité.\r\n * @param panel La description d'un panel\r\n */\r\n registerPanel(name: string, panel: PanelDescriptor): (() => void) | undefined {\r\n return () => {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\r\n name;\r\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\r\n panel;\r\n };\r\n }\r\n});\r\n","import {createContext} from \"react\";\r\n\r\nexport type CSSElement<T> = T & string & {_element: void};\r\nexport type CSSMod<N extends string, T> = N & T & string & {_mod: void};\r\nexport type CSSToStrings<T> = {[P in keyof T]?: string};\r\n\r\nexport type Mods<CSS, E> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer M, E> ? M : never}[keyof CSS];\r\nexport type ModNames<CSS, E> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer _, E> ? P : never}[keyof CSS];\r\nexport type BemFunction<CSS = any, P extends number | string | symbol = any, E = any> = ((object: true) => {\r\n [_ in ModNames<CSS, E> | P]: string;\r\n}) &\r\n (Mods<CSS, E> extends never | undefined ? () => string : (mods?: {[_ in Mods<CSS, E>]?: boolean}) => string);\r\n\r\nexport interface CSSContext {\r\n [key: string]: {[key: string]: BemFunction | string};\r\n}\r\n\r\nexport const ThemeContext = createContext<CSSContext>({});\r\n","import classNames from \"classnames\";\r\nimport {pick} from \"lodash\";\r\n\r\nimport {BemFunction, CSSElement, CSSMod, CSSToStrings} from \"./common\";\r\n\r\nexport type AllMods<CSS> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer _, infer __> ? P : never}[keyof CSS];\r\nexport type ToBem<CSS> = Omit<\r\n {\r\n [P in keyof CSS]-?: CSS[P] extends CSSElement<infer E>\r\n ? BemFunction<CSS, P, E>\r\n : CSS[P] extends CSSMod<infer __, infer ___>\r\n ? never\r\n : BemFunction<CSS, P, string>;\r\n },\r\n AllMods<CSS>\r\n>;\r\n\r\nexport type CSSProp<CSS> = CSSToStrings<CSS> | Partial<ToBem<CSS>>;\r\n\r\nexport function toBem<CSS>(css: CSS): ToBem<CSS> {\r\n const data: {[key: string]: string[]} = {};\r\n for (const key in css) {\r\n const [element, modifier] = key.split(\"--\");\r\n if (data[element] && modifier) {\r\n data[element].push(modifier);\r\n } else if (!data[element]) {\r\n data[element] = modifier ? [modifier] : [];\r\n }\r\n }\r\n\r\n return Object.keys(data).reduce(\r\n (bem, key) => ({\r\n ...bem,\r\n [key]: (mods: true | {[key: string]: boolean} = {}) => {\r\n if (mods !== true) {\r\n return classNames(\r\n (css as any)[key],\r\n ...data[key].filter(mod => mods[mod]).map(mod => (css as any)[`${key}--${mod}`])\r\n );\r\n } else {\r\n return pick(css, key, ...data[key].map(mod => `${key}--${mod}`));\r\n }\r\n }\r\n }),\r\n {}\r\n ) as ToBem<CSS>;\r\n}\r\n\r\nexport function fromBem<T>(css: CSSToStrings<T> | Partial<ToBem<T>> | T): CSSToStrings<T> {\r\n const res: CSSToStrings<T> = {};\r\n\r\n for (const key in css as any) {\r\n const value = (css as any)[key];\r\n if (value) {\r\n if (typeof value === \"string\") {\r\n (res as any)[key] = value;\r\n } else {\r\n Object.assign(res, value(true));\r\n }\r\n }\r\n }\r\n\r\n return res;\r\n}\r\n","import {useContext} from \"react\";\r\n\r\nimport {themeable} from \"@focus4/core\";\r\n\r\nimport {CSSToStrings, ThemeContext} from \"./common\";\r\nimport {fromBem, toBem, ToBem} from \"./to-bem\";\r\n\r\n/** Hook pour récupérer le theme du contexte et le fusionner avec d'autres. */\r\nexport function useTheme<T>(\r\n name: string,\r\n ...themes: (CSSToStrings<T> | Partial<ToBem<T>> | T | undefined)[]\r\n): ToBem<T> {\r\n const contextTheme = fromBem(useContext(ThemeContext)[name]) || {};\r\n return toBem(themeable(contextTheme, ...themes.filter(x => x).map(x => fromBem(x!))) as T);\r\n}\r\n","import {upperFirst} from \"lodash\";\r\nimport {useObserver} from \"mobx-react\";\r\nimport {FunctionComponent, ReactElement} from \"react\";\r\n\r\nimport {CSSToStrings} from \"./common\";\r\nimport {ToBem} from \"./to-bem\";\r\nimport {useTheme} from \"./use-theme\";\r\n\r\nexport interface ThemeConsumerProps<T> {\r\n children: (theme: ToBem<T>) => ReactElement;\r\n theme?: CSSToStrings<T> | Partial<ToBem<T>> | T;\r\n}\r\n\r\n/**\r\n * Crée un composant pour injecter le theme souhaité dans un composant, via une render props (à la place du HoC de `react-css-themr`).\r\n * @param name Le nom de la clé de theme.\r\n * @param localTheme Le theme local, fourni par le composant.\r\n */\r\nexport function themr<T>(name: string, localTheme?: T): FunctionComponent<ThemeConsumerProps<T>> {\r\n function TC({children, theme}: ThemeConsumerProps<T>) {\r\n const finalTheme = useTheme(name, localTheme, theme);\r\n return useObserver(() => children(finalTheme));\r\n }\r\n\r\n TC.displayName = `${upperFirst(name)}ThemeConsumer`;\r\n\r\n return TC;\r\n}\r\n"],"names":["_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"focus4.styling.js","sources":["../src/utils/animation.ts","../src/utils/color-scheme.ts","../src/utils/scroll-contexts.ts","../src/theme/common.ts","../src/theme/to-bem.ts","../src/theme/theme-provider.tsx","../src/theme/use-theme.ts","../src/theme/themr.tsx"],"sourcesContent":["function get() {\r\n const {animationDelay, animationDuration, animationTimingFunction} = window.getComputedStyle(document.body);\r\n\r\n const delay = toMs(animationDelay);\r\n const duration = toMs(animationDuration);\r\n const ease = animationTimingFunction.startsWith(\"cubic-bezier\")\r\n ? animationTimingFunction.substring(13).split(\",\").map(parseFloat)\r\n : undefined;\r\n\r\n return {delay, duration, ease};\r\n}\r\n\r\nexport function getDefaultTransition() {\r\n const {delay, duration, ease} = get();\r\n return {\r\n delay: delay / 1000,\r\n duration: duration / 1000,\r\n ease\r\n } as const;\r\n}\r\n\r\nexport function getSpringTransition() {\r\n return {\r\n type: \"spring\",\r\n bounce: 0,\r\n duration: get().duration / 1000\r\n } as const;\r\n}\r\n\r\nexport function cssTransitionProps({\r\n enter,\r\n enterActive,\r\n exit,\r\n exitActive\r\n}: {\r\n enter: string;\r\n enterActive: string;\r\n exit: string;\r\n exitActive: string;\r\n}) {\r\n const {delay, duration} = get();\r\n return {\r\n timeout: delay + duration,\r\n classNames: {\r\n enter,\r\n enterActive,\r\n exit,\r\n exitActive\r\n }\r\n };\r\n}\r\n\r\nfunction toMs(d: string) {\r\n if (d.endsWith(\"ms\")) {\r\n return +d.substring(0, d.length - 2);\r\n } else {\r\n return +d.substring(0, d.length - 1) * 1000;\r\n }\r\n}\r\n","import {autorun, observable} from \"mobx\";\r\n\r\nexport const colorScheme = observable({dark: false});\r\n\r\n/**\r\n * Permet d'initialiser l'utilisation du mode sombre dans une application Focus. Par défaut, il est initialisé avec le thème du navigateur de\r\n * l'utilisateur.\r\n * @param disableAutoDarkMode Désactive la prise en compte du thème de l'utilisateur et initialise toujours en thème clair.\r\n */\r\nexport function initColorScheme(disableAutoDarkMode = false) {\r\n const ls = localStorage.getItem(\"color-scheme\");\r\n if (ls === \"dark\" || (!ls && !disableAutoDarkMode && window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches)) {\r\n colorScheme.dark = true;\r\n }\r\n localStorage.setItem(\"color-scheme\", colorScheme.dark ? \"dark\" : \"light\");\r\n\r\n autorun(() => {\r\n const darkModeAttribute = document.documentElement.hasAttribute(\"dark\");\r\n if (colorScheme.dark && !darkModeAttribute) {\r\n document.documentElement.setAttribute(\"dark\", \"true\");\r\n localStorage.setItem(\"color-scheme\", \"dark\");\r\n } else if (!colorScheme.dark && darkModeAttribute) {\r\n document.documentElement.removeAttribute(\"dark\");\r\n localStorage.setItem(\"color-scheme\", \"light\");\r\n }\r\n });\r\n}\r\n","import {createContext, HTMLProps, ReactPortal} from \"react\";\r\n\r\nexport interface PanelDescriptor {\r\n node: HTMLDivElement;\r\n title?: string;\r\n}\r\n\r\n/** Contexte d'un Scrollable, expose les méthodes associées. */\r\nexport const ScrollableContext = createContext<{\r\n /**\r\n * Retourne la status du header.\r\n * @returns La taille du header et s'il est sticky ou non.\r\n */\r\n getHeaderStatus(): {sticky: boolean; height: number};\r\n /**\r\n * Affiche un élement dans le menu sticky du Scrollable\r\n * @param node Le noeud React.\r\n * @param parentNode Noeud à suivre pour positionner l'élément sticky.\r\n * @param retractable Menu rétractable.\r\n * @returns Le Portal associé.\r\n */\r\n menu(node: JSX.Element, parentNode: HTMLElement | null, retractable: boolean): ReactPortal | null;\r\n /**\r\n * Affiche un élement dans le Scrollable.\r\n * @param node Le noeud React.\r\n * @returns Le Portal associé.\r\n */\r\n portal(node: JSX.Element): ReactPortal;\r\n /**\r\n * Enregistre le header dans le Scrollable\r\n * @param nonStickyElement Le noeud DOM représentant le header non sticky.\r\n * @param canDeploy Précise si le header est toujours sticky ou non.\r\n * @returns Le disposer.\r\n */\r\n registerHeader(nonStickyElement: HTMLElement, canDeploy: boolean): () => void;\r\n /**\r\n * Set les props du header du Scrollable.\r\n * @param headerProps Les props du header.\r\n * @returns Le disposer.\r\n */\r\n registerHeaderProps(headerProps: HTMLProps<HTMLElement>): void;\r\n /**\r\n * Enregistre un observateur d'intersection avec le viewport du Scrollable.\r\n * @param node Le noeud DOM à observer.\r\n * @param onIntersect Le callback à appeler lors d'une intersection.\r\n * @returns Le disposer.\r\n */\r\n registerIntersect(node: HTMLElement, onIntersect: (ratio: number, isIntersecting: boolean) => void): () => void;\r\n /**\r\n * Scrolle vers la position demandée.\r\n * @param options Options.\r\n */\r\n scrollTo(options?: ScrollToOptions): void;\r\n}>({} as any);\r\n\r\n/** Contexte d'un ScrollspyContainer, expose les méthodes associées. */\r\nexport const ScrollspyContext = createContext({\r\n /**\r\n * Enregistre un panel dans le Scrollspu\r\n * @param name L'id du panel souhaité.\r\n * @param panel La description d'un panel\r\n */\r\n registerPanel(name: string, panel: PanelDescriptor): (() => void) | undefined {\r\n return () => {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\r\n name;\r\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\r\n panel;\r\n };\r\n }\r\n});\r\n","import {createContext} from \"react\";\r\n\r\nexport type CSSElement<T> = T & string & {_element: void};\r\nexport type CSSMod<N extends string, T> = N & T & string & {_mod: void};\r\nexport type CSSToStrings<T> = {[P in keyof T]?: string};\r\n\r\nexport type Mods<CSS, E> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer M, E> ? M : never}[keyof CSS];\r\nexport type ModNames<CSS, E> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer _, E> ? P : never}[keyof CSS];\r\nexport type BemFunction<CSS = any, P extends number | string | symbol = any, E = any> = ((object: true) => {\r\n [_ in ModNames<CSS, E> | P]: string;\r\n}) &\r\n (Mods<CSS, E> extends never | undefined ? () => string : (mods?: {[_ in Mods<CSS, E>]?: boolean}) => string);\r\n\r\nexport interface CSSTheme {\r\n [key: string]: BemFunction | string;\r\n}\r\n\r\nexport interface CSSContext {\r\n [key: string]: CSSTheme;\r\n}\r\n\r\nexport const ThemeContext = createContext<CSSContext>({});\r\n","import classNames from \"classnames\";\r\nimport {pick} from \"lodash\";\r\n\r\nimport {BemFunction, CSSElement, CSSMod, CSSToStrings} from \"./common\";\r\n\r\nexport type AllMods<CSS> = {[P in keyof CSS]: CSS[P] extends CSSMod<infer _, infer __> ? P : never}[keyof CSS];\r\nexport type ToBem<CSS> = Omit<\r\n {\r\n [P in keyof CSS]-?: CSS[P] extends CSSElement<infer E>\r\n ? BemFunction<CSS, P, E>\r\n : CSS[P] extends CSSMod<infer __, infer ___>\r\n ? never\r\n : BemFunction<CSS, P, string>;\r\n },\r\n AllMods<CSS>\r\n>;\r\n\r\nexport type CSSProp<CSS> = CSSToStrings<CSS> | Partial<ToBem<CSS>>;\r\n\r\n/**\r\n * `toBem` permet de transformer un objet de classes CSS, tel que celui importé d'un module CSS, dont les noms respectent la convention BEM\r\n * en un objet contenant une fonction par \"élément\" à laquelle on peut appliquer ses \"modificateurs\".\r\n *\r\n * Par exemple, un objet contenant les classes\r\n * ```ts\r\n * [\"panel\", \"panel--editing\", \"panel--loading\", \"title\", \"title--top\", \"title--bottom\"]\r\n * ```\r\n * sera transformé en un objet avec 2 fonctions `panel` et `title` :\r\n * ```ts\r\n * {\r\n * panel({editing?: boolean; loading?: boolean}) => string;\r\n * title({top?: boolean; bottom?: boolean}) => string;\r\n * }\r\n * ```\r\n * Un appel à une fonction retournera la classe CSS de l'\"élément\", à laquelle seront ajoutées ou non les classes des différents \"modificateurs\",\r\n * selon les valeurs des différents booléens.\r\n *\r\n * Vous pouvez utiliser `toBem` pour éviter d'avoir à concaténer des classes CSS à la main et pour rendre vos composants et votre CSS plus propres.\r\n * Son usage est bien évidemment totalement facultatif et à utiliser si cela vous arrange.\r\n *\r\n * _Remarque 1 : Les modules CSS importés doivent avoir des définitions Typescript générés par la commande `focus4 cssgen` du module `@focus4/tooling`._\r\n *\r\n * _Remarque 2 : Les propriétés `theme` des différents composants Focus acceptent aussi bien un objet CSS classique ou un objet créé par `toBem`._\r\n */\r\nexport function toBem<CSS>(css: CSS): ToBem<CSS> {\r\n const data: {[key: string]: string[]} = {};\r\n for (const key in css) {\r\n const [element, modifier] = key.split(\"--\");\r\n if (data[element] && modifier) {\r\n data[element].push(modifier);\r\n } else if (!data[element]) {\r\n data[element] = modifier ? [modifier] : [];\r\n }\r\n }\r\n\r\n return Object.keys(data).reduce(\r\n (bem, key) => ({\r\n ...bem,\r\n [key]: (mods: true | {[key: string]: boolean} = {}) => {\r\n if (mods !== true) {\r\n return classNames(\r\n (css as any)[key],\r\n ...data[key].filter(mod => mods[mod]).map(mod => (css as any)[`${key}--${mod}`])\r\n );\r\n } else {\r\n return pick(css, key, ...data[key].map(mod => `${key}--${mod}`));\r\n }\r\n }\r\n }),\r\n {}\r\n ) as ToBem<CSS>;\r\n}\r\n\r\n/**\r\n * `fromBem` permet de faire la transformation inverse de `toBem`, à savoir prendre l'objet résultant d'un appel à `toBem` et de ressortir un objet\r\n * qui contient toutes les classes CSS qui le compose.\r\n */\r\nexport function fromBem<T>(css: CSSToStrings<T> | Partial<ToBem<T>> | T): CSSToStrings<T> {\r\n const res: CSSToStrings<T> = {};\r\n\r\n for (const key in css as any) {\r\n const value = (css as any)[key];\r\n if (value) {\r\n if (typeof value === \"string\") {\r\n (res as any)[key] = value;\r\n } else {\r\n Object.assign(res, value(true));\r\n }\r\n }\r\n }\r\n\r\n return res;\r\n}\r\n","import {ReactNode, useContext, useMemo} from \"react\";\r\n\r\nimport {themeable} from \"@focus4/core\";\r\n\r\nimport {CSSContext, CSSTheme, ThemeContext} from \"./common\";\r\nimport {fromBem} from \"./to-bem\";\r\n\r\n/** Contient l'ensemble des classes CSS surchargeables (elles le sont toutes), regroupées par composant. */\r\nexport interface FocusCSSContext extends CSSContext {\r\n // Collections\r\n actionBar: CSSTheme;\r\n advancedSearch: CSSTheme;\r\n contextualActions: CSSTheme;\r\n dragLayer: CSSTheme;\r\n facet: CSSTheme;\r\n facetBox: CSSTheme;\r\n group: CSSTheme;\r\n list: CSSTheme;\r\n listBase: CSSTheme;\r\n searchBar: CSSTheme;\r\n summary: CSSTheme;\r\n table: CSSTheme;\r\n timeline: CSSTheme;\r\n\r\n // Forms\r\n booleanRadio: CSSTheme;\r\n display: CSSTheme;\r\n field: CSSTheme;\r\n form: CSSTheme;\r\n inputDate: CSSTheme;\r\n label: CSSTheme;\r\n panel: CSSTheme;\r\n select: CSSTheme;\r\n selectCheckbox: CSSTheme;\r\n selectChips: CSSTheme;\r\n selectRadio: CSSTheme;\r\n\r\n // Layout\r\n buttonBTT: CSSTheme;\r\n dialog: CSSTheme;\r\n header: CSSTheme;\r\n layout: CSSTheme;\r\n mainMenu: CSSTheme;\r\n overlay: CSSTheme;\r\n popin: CSSTheme;\r\n scrollable: CSSTheme;\r\n scrollspy: CSSTheme;\r\n\r\n // Toolbox\r\n autocomplete: CSSTheme;\r\n button: CSSTheme;\r\n calendar: CSSTheme;\r\n checkbox: CSSTheme;\r\n chip: CSSTheme;\r\n dropdown: CSSTheme;\r\n floatingActionButton: CSSTheme;\r\n iconButton: CSSTheme;\r\n menu: CSSTheme;\r\n progressIndicator: CSSTheme;\r\n radio: CSSTheme;\r\n ripple: CSSTheme;\r\n slider: CSSTheme;\r\n snackbar: CSSTheme;\r\n switch: CSSTheme;\r\n textField: CSSTheme;\r\n tabs: CSSTheme;\r\n tooltip: CSSTheme;\r\n}\r\n\r\n/** Props du ThemeProvider. */\r\nexport interface ThemeProviderProps {\r\n /** Objet faisant correspondre à un identifiant de composant son objet de classes CSS associé. */\r\n appTheme: Partial<FocusCSSContext>;\r\n /** Enfants. */\r\n children: ReactNode;\r\n}\r\n\r\n/**\r\n * Le `ThemeProvider` permet d'ajouter des classes CSS aux composants Focus (et autres composants utilisant `useTheme`) posés\r\n * à l'intérieur (via un context React).\r\n *\r\n * Les classes CSS ajoutées dans un `ThemeProvider` s'ajouteront aux éventuelles classes posées par un `ThemeProvider` parent,\r\n * y compris sur les mêmes composants.\r\n */\r\nexport function ThemeProvider({appTheme, children}: ThemeProviderProps) {\r\n const context = useContext(ThemeContext);\r\n\r\n const mergedContext = useMemo(() => {\r\n const mc = {} as CSSContext;\r\n\r\n for (const key in context) {\r\n if (key in appTheme && appTheme[key]) {\r\n mc[key] = themeable(fromBem(context[key]), fromBem(appTheme[key]!)) as CSSTheme;\r\n } else {\r\n mc[key] = context[key];\r\n }\r\n }\r\n\r\n for (const key in appTheme) {\r\n if (!(key in context) && appTheme[key]) {\r\n mc[key] = appTheme[key]!;\r\n }\r\n }\r\n return mc;\r\n }, [appTheme, context]);\r\n\r\n return <ThemeContext.Provider value={mergedContext}>{children}</ThemeContext.Provider>;\r\n}\r\n","import {useContext} from \"react\";\r\n\r\nimport {themeable} from \"@focus4/core\";\r\n\r\nimport {CSSToStrings, ThemeContext} from \"./common\";\r\nimport {fromBem, toBem, ToBem} from \"./to-bem\";\r\n\r\n/**\r\n * `useTheme` permet de récupérer les classes CSS passées dans un éventuel `ThemeProvider` parent et de les fusionner avec d'autres classes CSS\r\n * passées en paramètre.\r\n *\r\n * `useTheme` accepte aussi bien des objets de classes CSS classiques (importés d'un module CSS), que des objets créés avec `toBem`.\r\n *\r\n * @param name L'identifiant du composant dans le `appTheme` du `ThemeProvider`\r\n * @param themes Les objets de classes CSS à fusionner ensemble et avec celui du contexte.\r\n */\r\nexport function useTheme<T>(\r\n name: string,\r\n ...themes: (CSSToStrings<T> | Partial<ToBem<T>> | T | undefined)[]\r\n): ToBem<T> {\r\n const contextTheme = fromBem(useContext(ThemeContext)[name]) || {};\r\n return toBem(themeable(contextTheme, ...themes.filter(x => x).map(x => fromBem(x!))) as T);\r\n}\r\n","import {upperFirst} from \"lodash\";\r\nimport {useObserver} from \"mobx-react\";\r\nimport {FunctionComponent, ReactElement} from \"react\";\r\n\r\nimport {CSSToStrings} from \"./common\";\r\nimport {ToBem} from \"./to-bem\";\r\nimport {useTheme} from \"./use-theme\";\r\n\r\nexport interface ThemeConsumerProps<T> {\r\n children: (theme: ToBem<T>) => ReactElement;\r\n theme?: CSSToStrings<T> | Partial<ToBem<T>> | T;\r\n}\r\n\r\n/**\r\n * Permet de créer un composant wrapper pour utiliser `useTheme` dans le `render()` d'un composant classe.\r\n * @param name Le nom de la clé de theme.\r\n * @param localTheme Le theme local, fourni par le composant.\r\n */\r\nexport function themr<T>(name: string, localTheme?: T): FunctionComponent<ThemeConsumerProps<T>> {\r\n function TC({children, theme}: ThemeConsumerProps<T>) {\r\n const finalTheme = useTheme(name, localTheme, theme);\r\n return useObserver(() => children(finalTheme));\r\n }\r\n\r\n TC.displayName = `${upperFirst(name)}ThemeConsumer`;\r\n\r\n return TC;\r\n}\r\n"],"names":["_jsx"],"mappings":"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"}
|
package/lib/theme/common.d.ts
CHANGED
|
@@ -19,9 +19,10 @@ export type BemFunction<CSS = any, P extends number | string | symbol = any, E =
|
|
|
19
19
|
}) & (Mods<CSS, E> extends never | undefined ? () => string : (mods?: {
|
|
20
20
|
[_ in Mods<CSS, E>]?: boolean;
|
|
21
21
|
}) => string);
|
|
22
|
+
export interface CSSTheme {
|
|
23
|
+
[key: string]: BemFunction | string;
|
|
24
|
+
}
|
|
22
25
|
export interface CSSContext {
|
|
23
|
-
[key: string]:
|
|
24
|
-
[key: string]: BemFunction | string;
|
|
25
|
-
};
|
|
26
|
+
[key: string]: CSSTheme;
|
|
26
27
|
}
|
|
27
28
|
export declare const ThemeContext: import("react").Context<CSSContext>;
|
package/lib/theme/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { CSSContext, CSSElement, CSSMod, CSSTheme, CSSToStrings, ThemeContext } from "./common";
|
|
2
|
+
export { FocusCSSContext, ThemeProvider, ThemeProviderProps } from "./theme-provider";
|
|
2
3
|
export { themr } from "./themr";
|
|
3
4
|
export { CSSProp, ToBem, fromBem, toBem } from "./to-bem";
|
|
4
5
|
export { useTheme } from "./use-theme";
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { CSSContext, CSSTheme } from "./common";
|
|
3
|
+
/** Contient l'ensemble des classes CSS surchargeables (elles le sont toutes), regroupées par composant. */
|
|
4
|
+
export interface FocusCSSContext extends CSSContext {
|
|
5
|
+
actionBar: CSSTheme;
|
|
6
|
+
advancedSearch: CSSTheme;
|
|
7
|
+
contextualActions: CSSTheme;
|
|
8
|
+
dragLayer: CSSTheme;
|
|
9
|
+
facet: CSSTheme;
|
|
10
|
+
facetBox: CSSTheme;
|
|
11
|
+
group: CSSTheme;
|
|
12
|
+
list: CSSTheme;
|
|
13
|
+
listBase: CSSTheme;
|
|
14
|
+
searchBar: CSSTheme;
|
|
15
|
+
summary: CSSTheme;
|
|
16
|
+
table: CSSTheme;
|
|
17
|
+
timeline: CSSTheme;
|
|
18
|
+
booleanRadio: CSSTheme;
|
|
19
|
+
display: CSSTheme;
|
|
20
|
+
field: CSSTheme;
|
|
21
|
+
form: CSSTheme;
|
|
22
|
+
inputDate: CSSTheme;
|
|
23
|
+
label: CSSTheme;
|
|
24
|
+
panel: CSSTheme;
|
|
25
|
+
select: CSSTheme;
|
|
26
|
+
selectCheckbox: CSSTheme;
|
|
27
|
+
selectChips: CSSTheme;
|
|
28
|
+
selectRadio: CSSTheme;
|
|
29
|
+
buttonBTT: CSSTheme;
|
|
30
|
+
dialog: CSSTheme;
|
|
31
|
+
header: CSSTheme;
|
|
32
|
+
layout: CSSTheme;
|
|
33
|
+
mainMenu: CSSTheme;
|
|
34
|
+
overlay: CSSTheme;
|
|
35
|
+
popin: CSSTheme;
|
|
36
|
+
scrollable: CSSTheme;
|
|
37
|
+
scrollspy: CSSTheme;
|
|
38
|
+
autocomplete: CSSTheme;
|
|
39
|
+
button: CSSTheme;
|
|
40
|
+
calendar: CSSTheme;
|
|
41
|
+
checkbox: CSSTheme;
|
|
42
|
+
chip: CSSTheme;
|
|
43
|
+
dropdown: CSSTheme;
|
|
44
|
+
floatingActionButton: CSSTheme;
|
|
45
|
+
iconButton: CSSTheme;
|
|
46
|
+
menu: CSSTheme;
|
|
47
|
+
progressIndicator: CSSTheme;
|
|
48
|
+
radio: CSSTheme;
|
|
49
|
+
ripple: CSSTheme;
|
|
50
|
+
slider: CSSTheme;
|
|
51
|
+
snackbar: CSSTheme;
|
|
52
|
+
switch: CSSTheme;
|
|
53
|
+
textField: CSSTheme;
|
|
54
|
+
tabs: CSSTheme;
|
|
55
|
+
tooltip: CSSTheme;
|
|
56
|
+
}
|
|
57
|
+
/** Props du ThemeProvider. */
|
|
58
|
+
export interface ThemeProviderProps {
|
|
59
|
+
/** Objet faisant correspondre à un identifiant de composant son objet de classes CSS associé. */
|
|
60
|
+
appTheme: Partial<FocusCSSContext>;
|
|
61
|
+
/** Enfants. */
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Le `ThemeProvider` permet d'ajouter des classes CSS aux composants Focus (et autres composants utilisant `useTheme`) posés
|
|
66
|
+
* à l'intérieur (via un context React).
|
|
67
|
+
*
|
|
68
|
+
* Les classes CSS ajoutées dans un `ThemeProvider` s'ajouteront aux éventuelles classes posées par un `ThemeProvider` parent,
|
|
69
|
+
* y compris sur les mêmes composants.
|
|
70
|
+
*/
|
|
71
|
+
export declare function ThemeProvider({ appTheme, children }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
package/lib/theme/themr.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ThemeConsumerProps<T> {
|
|
|
6
6
|
theme?: CSSToStrings<T> | Partial<ToBem<T>> | T;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Permet de créer un composant wrapper pour utiliser `useTheme` dans le `render()` d'un composant classe.
|
|
10
10
|
* @param name Le nom de la clé de theme.
|
|
11
11
|
* @param localTheme Le theme local, fourni par le composant.
|
|
12
12
|
*/
|
package/lib/theme/to-bem.d.ts
CHANGED
|
@@ -6,5 +6,34 @@ export type ToBem<CSS> = Omit<{
|
|
|
6
6
|
[P in keyof CSS]-?: CSS[P] extends CSSElement<infer E> ? BemFunction<CSS, P, E> : CSS[P] extends CSSMod<infer __, infer ___> ? never : BemFunction<CSS, P, string>;
|
|
7
7
|
}, AllMods<CSS>>;
|
|
8
8
|
export type CSSProp<CSS> = CSSToStrings<CSS> | Partial<ToBem<CSS>>;
|
|
9
|
+
/**
|
|
10
|
+
* `toBem` permet de transformer un objet de classes CSS, tel que celui importé d'un module CSS, dont les noms respectent la convention BEM
|
|
11
|
+
* en un objet contenant une fonction par "élément" à laquelle on peut appliquer ses "modificateurs".
|
|
12
|
+
*
|
|
13
|
+
* Par exemple, un objet contenant les classes
|
|
14
|
+
* ```ts
|
|
15
|
+
* ["panel", "panel--editing", "panel--loading", "title", "title--top", "title--bottom"]
|
|
16
|
+
* ```
|
|
17
|
+
* sera transformé en un objet avec 2 fonctions `panel` et `title` :
|
|
18
|
+
* ```ts
|
|
19
|
+
* {
|
|
20
|
+
* panel({editing?: boolean; loading?: boolean}) => string;
|
|
21
|
+
* title({top?: boolean; bottom?: boolean}) => string;
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
* Un appel à une fonction retournera la classe CSS de l'"élément", à laquelle seront ajoutées ou non les classes des différents "modificateurs",
|
|
25
|
+
* selon les valeurs des différents booléens.
|
|
26
|
+
*
|
|
27
|
+
* Vous pouvez utiliser `toBem` pour éviter d'avoir à concaténer des classes CSS à la main et pour rendre vos composants et votre CSS plus propres.
|
|
28
|
+
* Son usage est bien évidemment totalement facultatif et à utiliser si cela vous arrange.
|
|
29
|
+
*
|
|
30
|
+
* _Remarque 1 : Les modules CSS importés doivent avoir des définitions Typescript générés par la commande `focus4 cssgen` du module `@focus4/tooling`._
|
|
31
|
+
*
|
|
32
|
+
* _Remarque 2 : Les propriétés `theme` des différents composants Focus acceptent aussi bien un objet CSS classique ou un objet créé par `toBem`._
|
|
33
|
+
*/
|
|
9
34
|
export declare function toBem<CSS>(css: CSS): ToBem<CSS>;
|
|
35
|
+
/**
|
|
36
|
+
* `fromBem` permet de faire la transformation inverse de `toBem`, à savoir prendre l'objet résultant d'un appel à `toBem` et de ressortir un objet
|
|
37
|
+
* qui contient toutes les classes CSS qui le compose.
|
|
38
|
+
*/
|
|
10
39
|
export declare function fromBem<T>(css: CSSToStrings<T> | Partial<ToBem<T>> | T): CSSToStrings<T>;
|
package/lib/theme/use-theme.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { CSSToStrings } from "./common";
|
|
2
2
|
import { ToBem } from "./to-bem";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* `useTheme` permet de récupérer les classes CSS passées dans un éventuel `ThemeProvider` parent et de les fusionner avec d'autres classes CSS
|
|
5
|
+
* passées en paramètre.
|
|
6
|
+
*
|
|
7
|
+
* `useTheme` accepte aussi bien des objets de classes CSS classiques (importés d'un module CSS), que des objets créés avec `toBem`.
|
|
8
|
+
*
|
|
9
|
+
* @param name L'identifiant du composant dans le `appTheme` du `ThemeProvider`
|
|
10
|
+
* @param themes Les objets de classes CSS à fusionner ensemble et avec celui du contexte.
|
|
11
|
+
*/
|
|
4
12
|
export declare function useTheme<T>(name: string, ...themes: (CSSToStrings<T> | Partial<ToBem<T>> | T | undefined)[]): ToBem<T>;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export declare const colorScheme: {
|
|
2
2
|
dark: boolean;
|
|
3
3
|
};
|
|
4
|
+
/**
|
|
5
|
+
* Permet d'initialiser l'utilisation du mode sombre dans une application Focus. Par défaut, il est initialisé avec le thème du navigateur de
|
|
6
|
+
* l'utilisateur.
|
|
7
|
+
* @param disableAutoDarkMode Désactive la prise en compte du thème de l'utilisateur et initialise toujours en thème clair.
|
|
8
|
+
*/
|
|
4
9
|
export declare function initColorScheme(disableAutoDarkMode?: boolean): void;
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { cssTransitionProps, getDefaultTransition, getSpringTransition } from "./animation";
|
|
2
|
-
export { getIcon } from "./get-icon";
|
|
3
2
|
export { colorScheme, initColorScheme } from "./color-scheme";
|
|
4
3
|
export { PanelDescriptor, ScrollableContext, ScrollspyContext } from "./scroll-contexts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@focus4/styling",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.15.0",
|
|
4
4
|
"description": "Focus v4, styling module",
|
|
5
5
|
"main": "lib/focus4.styling.js",
|
|
6
6
|
"repository": {
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
"test-ci": "jest --ci --reporters=default --reporters=jest-junit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@focus4/core": "11.
|
|
22
|
-
"@types/react-dom": "18.2.
|
|
21
|
+
"@focus4/core": "11.15.0",
|
|
22
|
+
"@types/react-dom": "18.2.19",
|
|
23
23
|
"classnames": "2.5.1",
|
|
24
24
|
"mobx-react": "7.6.0",
|
|
25
25
|
"react": "18.2.0",
|
|
26
26
|
"react-dom": "18.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/jest": "29.5.
|
|
29
|
+
"@types/jest": "29.5.12",
|
|
30
30
|
"jest": "29.7.0",
|
|
31
31
|
"jest-junit": "16.0.0",
|
|
32
|
-
"ts-jest": "29.1.
|
|
32
|
+
"ts-jest": "29.1.2"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "6e2a358d6b91c70e4c4ab78eb4b3442cc69d1ce8"
|
|
35
35
|
}
|
package/lib/utils/get-icon.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* Récupère l'icône correspondante au nom.
|
|
4
|
-
* @param name Le nom de l'icône.
|
|
5
|
-
* @param isCustom Icône custom ou non.
|
|
6
|
-
*/
|
|
7
|
-
export declare function getIcon(name: ReactNode, isCustom: boolean): JSX.Element | string;
|
|
8
|
-
/**
|
|
9
|
-
* Récupère l'icône par sa clé i18n.
|
|
10
|
-
* @param i18nKey La clé i18n de l'icône.
|
|
11
|
-
*/
|
|
12
|
-
export declare function getIcon(i18nKey: string): JSX.Element | string;
|