@salt-ds/styles 0.2.1 → 0.3.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/CHANGELOG.md +61 -0
- package/dist-cjs/index.js +9 -7
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/style-injection-provider/index.js +2 -7
- package/dist-cjs/style-injection-provider/index.js.map +1 -1
- package/dist-cjs/use-style-injection/InsertionPointProvider.js +1 -6
- package/dist-cjs/use-style-injection/InsertionPointProvider.js.map +1 -1
- package/dist-cjs/use-style-injection/useStyleInjection.js +10 -12
- package/dist-cjs/use-style-injection/useStyleInjection.js.map +1 -1
- package/dist-cjs/useClassNameInjection.js +75 -0
- package/dist-cjs/useClassNameInjection.js.map +1 -0
- package/dist-es/index.js +3 -2
- package/dist-es/index.js.map +1 -1
- package/dist-es/style-injection-provider/index.js +2 -5
- package/dist-es/style-injection-provider/index.js.map +1 -1
- package/dist-es/use-style-injection/InsertionPointProvider.js +1 -4
- package/dist-es/use-style-injection/InsertionPointProvider.js.map +1 -1
- package/dist-es/use-style-injection/useStyleInjection.js +7 -6
- package/dist-es/use-style-injection/useStyleInjection.js.map +1 -1
- package/dist-es/useClassNameInjection.js +71 -0
- package/dist-es/useClassNameInjection.js.map +1 -0
- package/dist-types/index.d.ts +2 -1
- package/dist-types/style-injection-provider/index.d.ts +1 -1
- package/dist-types/use-style-injection/InsertionPointProvider.d.ts +2 -2
- package/dist-types/use-style-injection/index.d.ts +1 -1
- package/dist-types/useClassNameInjection.d.ts +39 -0
- package/package.json +7 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @salt-ds/styles
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 27c4338: This feature is in-development, for exploration and feedback only.
|
|
8
|
+
|
|
9
|
+
Introduce a context‑driven API for injecting CSS class names into Salt components based on their props, and optionally stripping implementation‑only props before forwarding.
|
|
10
|
+
|
|
11
|
+
_Status_
|
|
12
|
+
Non‑breaking for existing Salt consumers
|
|
13
|
+
Experimental and incomplete — interfaces and behavior may change without notice
|
|
14
|
+
|
|
15
|
+
**Note to JPM employees**
|
|
16
|
+
Use only in non‑production codebases, or with prior permission from the Salt engineering team
|
|
17
|
+
What’s included
|
|
18
|
+
|
|
19
|
+
- `ClassNameInjectionProvider` — supplies a registry of class injectors via React context
|
|
20
|
+
- `useClassNameInjection(component, props)`
|
|
21
|
+
- computes additional classes via registered injectors
|
|
22
|
+
- merges them with any className provided at the call site
|
|
23
|
+
- removes internal/derived props (declared by each injector) before forwarding
|
|
24
|
+
- `registerClassInjector(registry, component, keys, injector)` — registers per‑component injection rules
|
|
25
|
+
|
|
26
|
+
_Documentation_
|
|
27
|
+
Full documentation will follow once the API is stabilized; for now, consider this API private and subject to change.
|
|
28
|
+
|
|
29
|
+
## 0.2.1
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- f7fcbd11: Fixed issue where components are not injecting their styles.
|
|
34
|
+
|
|
35
|
+
## 0.2.0
|
|
36
|
+
|
|
37
|
+
### Minor Changes
|
|
38
|
+
|
|
39
|
+
- 02815995: Updated `useComponentCssInjection` to not inject styles when configured by the SaltProvider.
|
|
40
|
+
|
|
41
|
+
## 0.1.2
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 45eaeeb5: Fix `useInsertionEffect` not found error bundled by Webpack
|
|
46
|
+
|
|
47
|
+
## 0.1.1
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- abfc4364: Corrected the minimum supported version of React. It has been updated to 16.14.0 due to the support for the new [JSX transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)
|
|
52
|
+
|
|
53
|
+
## 0.1.0
|
|
54
|
+
|
|
55
|
+
### Minor Changes
|
|
56
|
+
|
|
57
|
+
- d78ff537: Added @salt-ds/styles and @salt-ds/window packages
|
|
58
|
+
|
|
59
|
+
These packages are introduced to support uses of Salt in a desktop application where pop-out elements such as tooltips are rendered into separate windows with no previously added CSS.
|
|
60
|
+
|
|
61
|
+
The insertion point where useComponentCssInjection inserts styles can be controlled via InsertionPointContext
|
package/dist-cjs/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var useStyleInjection = require('./use-style-injection/useStyleInjection.js');
|
|
6
|
-
var InsertionPointProvider = require('./use-style-injection/InsertionPointProvider.js');
|
|
7
3
|
var index = require('./style-injection-provider/index.js');
|
|
4
|
+
var InsertionPointProvider = require('./use-style-injection/InsertionPointProvider.js');
|
|
5
|
+
var useStyleInjection = require('./use-style-injection/useStyleInjection.js');
|
|
6
|
+
var useClassNameInjection = require('./useClassNameInjection.js');
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
exports.useComponentCssInjection = useStyleInjection.useComponentCssInjection;
|
|
12
|
-
exports.InsertionPointProvider = InsertionPointProvider.InsertionPointProvider;
|
|
13
|
-
exports.useInsertionPoint = InsertionPointProvider.useInsertionPoint;
|
|
14
10
|
exports.StyleInjectionProvider = index.StyleInjectionProvider;
|
|
15
11
|
exports.useStyleInjection = index.useStyleInjection;
|
|
12
|
+
exports.InsertionPointProvider = InsertionPointProvider.InsertionPointProvider;
|
|
13
|
+
exports.useInsertionPoint = InsertionPointProvider.useInsertionPoint;
|
|
14
|
+
exports.useComponentCssInjection = useStyleInjection.useComponentCssInjection;
|
|
15
|
+
exports.ClassNameInjectionProvider = useClassNameInjection.ClassNameInjectionProvider;
|
|
16
|
+
exports.registerClassInjector = useClassNameInjection.registerClassInjector;
|
|
17
|
+
exports.useClassNameInjection = useClassNameInjection.useClassNameInjection;
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
4
|
var React = require('react');
|
|
7
5
|
|
|
8
6
|
const StyleInjectionContext = React.createContext(true);
|
|
9
7
|
function useStyleInjection(enableStyleInjection) {
|
|
10
8
|
const enableStyleInjectionFromContext = React.useContext(StyleInjectionContext);
|
|
11
|
-
return enableStyleInjection
|
|
9
|
+
return enableStyleInjection ?? enableStyleInjectionFromContext;
|
|
12
10
|
}
|
|
13
11
|
function StyleInjectionProvider(props) {
|
|
14
12
|
const { value: enableStyleInjectionProp, children } = props;
|
|
15
13
|
const value = useStyleInjection(enableStyleInjectionProp);
|
|
16
|
-
return /* @__PURE__ */ jsxRuntime.jsx(StyleInjectionContext.Provider, {
|
|
17
|
-
value,
|
|
18
|
-
children
|
|
19
|
-
});
|
|
14
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StyleInjectionContext.Provider, { value, children });
|
|
20
15
|
}
|
|
21
16
|
|
|
22
17
|
exports.StyleInjectionProvider = StyleInjectionProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/style-injection-provider/index.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/style-injection-provider/index.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nexport interface StyleInjectionContextType {\n value?: boolean;\n}\n\nconst StyleInjectionContext = createContext(true);\n\nexport function useStyleInjection(enableStyleInjection?: boolean): boolean {\n const enableStyleInjectionFromContext = useContext(StyleInjectionContext);\n return enableStyleInjection ?? enableStyleInjectionFromContext;\n}\n\nexport interface StyleInjectionProviderProps extends StyleInjectionContextType {\n children: ReactNode;\n}\n\nexport function StyleInjectionProvider(props: StyleInjectionProviderProps) {\n const { value: enableStyleInjectionProp, children } = props;\n const value = useStyleInjection(enableStyleInjectionProp);\n\n return (\n <StyleInjectionContext.Provider value={value}>\n {children}\n </StyleInjectionContext.Provider>\n );\n}\n"],"names":["createContext","useContext","jsx"],"mappings":";;;;;AAKA,MAAM,qBAAA,GAAwBA,oBAAc,IAAI,CAAA;AAEzC,SAAS,kBAAkB,oBAAA,EAAyC;AACzE,EAAA,MAAM,+BAAA,GAAkCC,iBAAW,qBAAqB,CAAA;AACxE,EAAA,OAAO,oBAAA,IAAwB,+BAAA;AACjC;AAMO,SAAS,uBAAuB,KAAA,EAAoC;AACzE,EAAA,MAAM,EAAE,KAAA,EAAO,wBAAA,EAA0B,QAAA,EAAS,GAAI,KAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,kBAAkB,wBAAwB,CAAA;AAExD,EAAA,uBACEC,cAAA,CAAC,qBAAA,CAAsB,QAAA,EAAtB,EAA+B,OAC7B,QAAA,EACH,CAAA;AAEJ;;;;;"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
4
|
var React = require('react');
|
|
7
5
|
|
|
@@ -12,10 +10,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
12
10
|
function InsertionPointProvider(props) {
|
|
13
11
|
const { insertionPoint: insertionPointProp, children } = props;
|
|
14
12
|
const value = React.useMemo(() => insertionPointProp, [insertionPointProp]);
|
|
15
|
-
return /* @__PURE__ */ jsxRuntime.jsx(InsertionPointContext.Provider, {
|
|
16
|
-
value,
|
|
17
|
-
children
|
|
18
|
-
});
|
|
13
|
+
return /* @__PURE__ */ jsxRuntime.jsx(InsertionPointContext.Provider, { value, children });
|
|
19
14
|
}
|
|
20
15
|
function useInsertionPoint() {
|
|
21
16
|
const value = React.useContext(InsertionPointContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InsertionPointProvider.js","sources":["../src/use-style-injection/InsertionPointProvider.tsx"],"sourcesContent":["import { createContext, ReactNode, useContext, useMemo } from \"react\";\n\nexport interface InsertionPointContextType {\n insertionPoint: ChildNode | null;\n}\n\nconst InsertionPointContext = createContext<ChildNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n InsertionPointContext.displayName = \"InsertionPointContext\";\n}\n\nexport interface InsertionPointProviderProps extends InsertionPointContextType {\n children: ReactNode;\n}\n\nexport function InsertionPointProvider(props: InsertionPointProviderProps) {\n const { insertionPoint: insertionPointProp, children } = props;\n const value = useMemo(() => insertionPointProp, [insertionPointProp]);\n\n return (\n <InsertionPointContext.Provider value={value}>\n {children}\n </InsertionPointContext.Provider>\n );\n}\n\nexport function useInsertionPoint() {\n const value = useContext(InsertionPointContext);\n return value;\n}\n"],"names":["createContext","useMemo","jsx","useContext"],"mappings":"
|
|
1
|
+
{"version":3,"file":"InsertionPointProvider.js","sources":["../src/use-style-injection/InsertionPointProvider.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\nexport interface InsertionPointContextType {\n insertionPoint: ChildNode | null;\n}\n\nconst InsertionPointContext = createContext<ChildNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n InsertionPointContext.displayName = \"InsertionPointContext\";\n}\n\nexport interface InsertionPointProviderProps extends InsertionPointContextType {\n children: ReactNode;\n}\n\nexport function InsertionPointProvider(props: InsertionPointProviderProps) {\n const { insertionPoint: insertionPointProp, children } = props;\n const value = useMemo(() => insertionPointProp, [insertionPointProp]);\n\n return (\n <InsertionPointContext.Provider value={value}>\n {children}\n </InsertionPointContext.Provider>\n );\n}\n\nexport function useInsertionPoint() {\n const value = useContext(InsertionPointContext);\n return value;\n}\n"],"names":["createContext","useMemo","jsx","useContext"],"mappings":";;;;;AAMA,MAAM,qBAAA,GAAwBA,oBAAgC,IAAI,CAAA;AAElE,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc;AACzC,EAAA,qBAAA,CAAsB,WAAA,GAAc,uBAAA;AACtC;AAMO,SAAS,uBAAuB,KAAA,EAAoC;AACzE,EAAA,MAAM,EAAE,cAAA,EAAgB,kBAAA,EAAoB,QAAA,EAAS,GAAI,KAAA;AACzD,EAAA,MAAM,QAAQC,aAAA,CAAQ,MAAM,kBAAA,EAAoB,CAAC,kBAAkB,CAAC,CAAA;AAEpE,EAAA,uBACEC,cAAA,CAAC,qBAAA,CAAsB,QAAA,EAAtB,EAA+B,OAC7B,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,KAAA,GAAQC,iBAAW,qBAAqB,CAAA;AAC9C,EAAA,OAAO,KAAA;AACT;;;;;"}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var React = require('react');
|
|
6
|
-
var InsertionPointProvider = require('./InsertionPointProvider.js');
|
|
7
4
|
var index = require('../style-injection-provider/index.js');
|
|
5
|
+
var InsertionPointProvider = require('./InsertionPointProvider.js');
|
|
8
6
|
|
|
9
|
-
function
|
|
10
|
-
if (e && e.__esModule) return e;
|
|
7
|
+
function _interopNamespaceDefault(e) {
|
|
11
8
|
var n = Object.create(null);
|
|
12
9
|
if (e) {
|
|
13
10
|
Object.keys(e).forEach(function (k) {
|
|
@@ -20,14 +17,16 @@ function _interopNamespace(e) {
|
|
|
20
17
|
}
|
|
21
18
|
});
|
|
22
19
|
}
|
|
23
|
-
n
|
|
20
|
+
n.default = e;
|
|
24
21
|
return n;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
var React__namespace = /*#__PURE__*/
|
|
24
|
+
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const maybeUseInsertionEffect = (
|
|
27
|
+
// biome-ignore lint/suspicious/noExplicitAny: see comment above
|
|
28
|
+
React__namespace["useInsertionEffect".toString()] ?? React__namespace.useLayoutEffect
|
|
29
|
+
);
|
|
31
30
|
const windowSheetsMap = /* @__PURE__ */ new WeakMap();
|
|
32
31
|
function useComponentCssInjection({
|
|
33
32
|
testId,
|
|
@@ -37,12 +36,11 @@ function useComponentCssInjection({
|
|
|
37
36
|
const styleInjectionEnabled = index.useStyleInjection();
|
|
38
37
|
const insertionPoint = InsertionPointProvider.useInsertionPoint();
|
|
39
38
|
maybeUseInsertionEffect(() => {
|
|
40
|
-
var _a2, _b;
|
|
41
39
|
if (!targetWindow || !styleInjectionEnabled) {
|
|
42
40
|
return;
|
|
43
41
|
}
|
|
44
|
-
const sheetsMap =
|
|
45
|
-
const styleMap =
|
|
42
|
+
const sheetsMap = windowSheetsMap.get(targetWindow) ?? /* @__PURE__ */ new Map();
|
|
43
|
+
const styleMap = sheetsMap.get(css) ?? { styleElement: null, count: 0 };
|
|
46
44
|
if (styleMap.styleElement == null) {
|
|
47
45
|
styleMap.styleElement = targetWindow.document.createElement("style");
|
|
48
46
|
styleMap.styleElement.setAttribute("type", "text/css");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStyleInjection.js","sources":["../src/use-style-injection/useStyleInjection.ts"],"sourcesContent":["import * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"useStyleInjection.js","sources":["../src/use-style-injection/useStyleInjection.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useStyleInjection } from \"../style-injection-provider\";\nimport { useInsertionPoint } from \"./InsertionPointProvider\";\n\n/* Workaround for https://github.com/webpack/webpack/issues/14814#issuecomment-1536757985 */\nconst maybeUseInsertionEffect: typeof React.useLayoutEffect =\n // biome-ignore lint/suspicious/noExplicitAny: see comment above\n (React as any)[\"useInsertionEffect\".toString()] ?? React.useLayoutEffect;\n\nexport interface UseComponentCssInjection {\n testId?: string;\n css: string;\n window?: Window | null;\n}\n\ntype StyleElementMap = Map<\n string,\n { styleElement: HTMLStyleElement | null; count: number }\n>;\n\n// windowSheetsMap maps window objects to StyleElementMaps\n// A StyleElementMap maps css strings to style element tags\nconst windowSheetsMap = new WeakMap<Window, StyleElementMap>();\n\nexport function useComponentCssInjection({\n testId,\n css,\n window: targetWindow,\n}: UseComponentCssInjection): void {\n const styleInjectionEnabled = useStyleInjection();\n const insertionPoint = useInsertionPoint();\n\n maybeUseInsertionEffect(() => {\n if (!targetWindow || !styleInjectionEnabled) {\n return;\n }\n\n const sheetsMap =\n windowSheetsMap.get(targetWindow) ??\n new Map<\n string,\n { styleElement: HTMLStyleElement | null; count: number }\n >();\n const styleMap = sheetsMap.get(css) ?? { styleElement: null, count: 0 };\n\n if (styleMap.styleElement == null) {\n styleMap.styleElement = targetWindow.document.createElement(\"style\");\n styleMap.styleElement.setAttribute(\"type\", \"text/css\");\n styleMap.styleElement.setAttribute(\"data-salt-style\", testId || \"\");\n styleMap.styleElement.textContent = css;\n\n styleMap.count = 1;\n\n targetWindow.document.head.insertBefore(\n styleMap.styleElement,\n insertionPoint || targetWindow.document.head.firstChild,\n );\n } else {\n styleMap.styleElement.textContent = css;\n styleMap.count++;\n }\n sheetsMap.set(css, styleMap);\n windowSheetsMap.set(targetWindow, sheetsMap);\n\n return () => {\n const sheetsMap = windowSheetsMap.get(targetWindow);\n const styleMap = sheetsMap?.get(css);\n if (styleMap?.styleElement) {\n styleMap.count--;\n if (styleMap.count < 1) {\n targetWindow.document.head.removeChild(styleMap.styleElement);\n styleMap.styleElement = null;\n sheetsMap?.delete(css);\n }\n }\n };\n }, [testId, css, targetWindow]);\n}\n"],"names":["React","useStyleInjection","useInsertionPoint","sheetsMap","styleMap"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAM,uBAAA;AAAA;AAAA,EAEHA,gBAAA,CAAc,oBAAA,CAAqB,QAAA,EAAU,KAAKA,gBAAA,CAAM;AAAA,CAAA;AAe3D,MAAM,eAAA,uBAAsB,OAAA,EAAiC;AAEtD,SAAS,wBAAA,CAAyB;AAAA,EACvC,MAAA;AAAA,EACA,GAAA;AAAA,EACA,MAAA,EAAQ;AACV,CAAA,EAAmC;AACjC,EAAA,MAAM,wBAAwBC,uBAAA,EAAkB;AAChD,EAAA,MAAM,iBAAiBC,wCAAA,EAAkB;AAEzC,EAAA,uBAAA,CAAwB,MAAM;AAC5B,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,qBAAA,EAAuB;AAC3C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YACJ,eAAA,CAAgB,GAAA,CAAI,YAAY,CAAA,wBAC5B,GAAA,EAGF;AACJ,IAAA,MAAM,QAAA,GAAW,UAAU,GAAA,CAAI,GAAG,KAAK,EAAE,YAAA,EAAc,IAAA,EAAM,KAAA,EAAO,CAAA,EAAE;AAEtE,IAAA,IAAI,QAAA,CAAS,gBAAgB,IAAA,EAAM;AACjC,MAAA,QAAA,CAAS,YAAA,GAAe,YAAA,CAAa,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AACnE,MAAA,QAAA,CAAS,YAAA,CAAa,YAAA,CAAa,MAAA,EAAQ,UAAU,CAAA;AACrD,MAAA,QAAA,CAAS,YAAA,CAAa,YAAA,CAAa,iBAAA,EAAmB,MAAA,IAAU,EAAE,CAAA;AAClE,MAAA,QAAA,CAAS,aAAa,WAAA,GAAc,GAAA;AAEpC,MAAA,QAAA,CAAS,KAAA,GAAQ,CAAA;AAEjB,MAAA,YAAA,CAAa,SAAS,IAAA,CAAK,YAAA;AAAA,QACzB,QAAA,CAAS,YAAA;AAAA,QACT,cAAA,IAAkB,YAAA,CAAa,QAAA,CAAS,IAAA,CAAK;AAAA,OAC/C;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,aAAa,WAAA,GAAc,GAAA;AACpC,MAAA,QAAA,CAAS,KAAA,EAAA;AAAA,IACX;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,KAAK,QAAQ,CAAA;AAC3B,IAAA,eAAA,CAAgB,GAAA,CAAI,cAAc,SAAS,CAAA;AAE3C,IAAA,OAAO,MAAM;AACX,MAAA,MAAMC,UAAAA,GAAY,eAAA,CAAgB,GAAA,CAAI,YAAY,CAAA;AAClD,MAAA,MAAMC,SAAAA,GAAWD,UAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,UAAAA,CAAW,GAAA,CAAI,GAAA,CAAA;AAChC,MAAA,IAAIC,SAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,SAAAA,CAAU,YAAA,EAAc;AAC1B,QAAAA,SAAAA,CAAS,KAAA,EAAA;AACT,QAAA,IAAIA,SAAAA,CAAS,QAAQ,CAAA,EAAG;AACtB,UAAA,YAAA,CAAa,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYA,SAAAA,CAAS,YAAY,CAAA;AAC5D,UAAAA,UAAS,YAAA,GAAe,IAAA;AACxB,UAAAD,UAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,UAAAA,CAAW,MAAA,CAAO,GAAA,CAAA;AAAA,QACpB;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,GAAA,EAAK,YAAY,CAAC,CAAA;AAChC;;;;"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
const EMPTY_REGISTRY = /* @__PURE__ */ new Map();
|
|
8
|
+
const InjectionContext = React.createContext(EMPTY_REGISTRY);
|
|
9
|
+
let hasWarnedExperimentalOnce = false;
|
|
10
|
+
function ClassNameInjectionProvider({
|
|
11
|
+
children,
|
|
12
|
+
value
|
|
13
|
+
}) {
|
|
14
|
+
const registry = React.useMemo(() => value ?? EMPTY_REGISTRY, [value]);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
if (!hasWarnedExperimentalOnce && process.env.NODE_ENV !== "production") {
|
|
17
|
+
console.warn(
|
|
18
|
+
"Salt ClassNameInjectionProvider is experimental and subject to change. JPM users: only recommended in non-production environments or with prior permission from the Salt team."
|
|
19
|
+
);
|
|
20
|
+
hasWarnedExperimentalOnce = true;
|
|
21
|
+
}
|
|
22
|
+
}, []);
|
|
23
|
+
return /* @__PURE__ */ jsxRuntime.jsx(InjectionContext.Provider, { value: registry, children });
|
|
24
|
+
}
|
|
25
|
+
function useClassNameInjection(component, props) {
|
|
26
|
+
const registry = React.useContext(InjectionContext);
|
|
27
|
+
const entries = registry.get(component) ?? [];
|
|
28
|
+
const deps = React.useMemo(
|
|
29
|
+
() => entries.length ? entries.flatMap((e) => e.keys.map((k) => props[k])) : [],
|
|
30
|
+
[entries, props]
|
|
31
|
+
);
|
|
32
|
+
const injected = React.useMemo(() => {
|
|
33
|
+
const { className: _ignore, ...restProps } = props;
|
|
34
|
+
if (!entries.length) return [];
|
|
35
|
+
return entries.map((e) => e.fn(restProps)).filter((v) => v != null);
|
|
36
|
+
}, [entries, deps, props]);
|
|
37
|
+
const className = React.useMemo(
|
|
38
|
+
() => clsx.clsx(props.className, injected) || void 0,
|
|
39
|
+
[props, injected]
|
|
40
|
+
);
|
|
41
|
+
const cleanProps = React.useMemo(() => {
|
|
42
|
+
const { className: _ignore, ...restProps } = props;
|
|
43
|
+
if (!entries.length) {
|
|
44
|
+
return restProps;
|
|
45
|
+
}
|
|
46
|
+
const copy = { ...restProps };
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
for (const key of entry.keys) {
|
|
49
|
+
if (Object.hasOwn(copy, key)) {
|
|
50
|
+
delete copy[key];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return copy;
|
|
55
|
+
}, [entries, deps, props]);
|
|
56
|
+
return { className, props: cleanProps };
|
|
57
|
+
}
|
|
58
|
+
function registerClassInjector(registry, component, keys, injector) {
|
|
59
|
+
if (!registry.has(component)) {
|
|
60
|
+
registry.set(component, []);
|
|
61
|
+
}
|
|
62
|
+
const wrapped = (props) => {
|
|
63
|
+
const picked = Object.fromEntries(keys.map((k) => [k, props[k]]));
|
|
64
|
+
return injector(picked);
|
|
65
|
+
};
|
|
66
|
+
registry.get(component).push({
|
|
67
|
+
fn: wrapped,
|
|
68
|
+
keys
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
exports.ClassNameInjectionProvider = ClassNameInjectionProvider;
|
|
73
|
+
exports.registerClassInjector = registerClassInjector;
|
|
74
|
+
exports.useClassNameInjection = useClassNameInjection;
|
|
75
|
+
//# sourceMappingURL=useClassNameInjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useClassNameInjection.js","sources":["../src/useClassNameInjection.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n} from \"react\";\n\n/**\n * Extensible map of supported components → their props.\n * @salt-ds/core must augment this with the components that support the API,\n * using the same key string that the component passes to useClassNameInjection,\n * e.g., \"saltButton\": ButtonProps.\n */\nexport interface ComponentPropsMap {}\n\ntype SupportedComponent = keyof ComponentPropsMap extends never\n ? \"ComponentPropsMap must be augmented to define the components that support useClassNameInjection\"\n : keyof ComponentPropsMap;\n\nexport type ClassNameInjector<Props, Keys extends keyof Props> = (\n props: Pick<Props, Keys>,\n) => string | undefined;\n\ninterface ClassNameInjectorEntry {\n fn: (props: unknown) => string | undefined;\n keys: string[];\n}\n\nexport type ClassNameInjectionRegistry<\n ComponentName extends SupportedComponent = SupportedComponent,\n> = Map<ComponentName, ClassNameInjectorEntry[]>;\n\nconst EMPTY_REGISTRY: ClassNameInjectionRegistry = new Map();\nconst InjectionContext =\n createContext<ClassNameInjectionRegistry>(EMPTY_REGISTRY);\n\nexport type ClassNameInjectionProviderProps = {\n children: ReactNode;\n value?: ClassNameInjectionRegistry;\n};\n\nlet hasWarnedExperimentalOnce = false;\n\nexport function ClassNameInjectionProvider({\n children,\n value,\n}: ClassNameInjectionProviderProps) {\n const registry = useMemo(() => value ?? EMPTY_REGISTRY, [value]);\n\n useEffect(() => {\n if (!hasWarnedExperimentalOnce && process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"Salt ClassNameInjectionProvider is experimental and subject to change. JPM users: only recommended in non-production environments or with prior permission from the Salt team.\",\n );\n hasWarnedExperimentalOnce = true;\n }\n }, []);\n\n return (\n <InjectionContext.Provider value={registry}>\n {children}\n </InjectionContext.Provider>\n );\n}\n\ntype PropsWithClassName = { className?: string } & Record<string, any>;\n\n/**\n * Return the className created by the registry and a props object with injector keys stripped.\n * Only components declared in ComponentPropsMap can call this at compile time.\n */\nexport function useClassNameInjection<Props extends PropsWithClassName>(\n component: SupportedComponent,\n props: Props,\n): { className: string | undefined; props: Omit<Props, \"className\"> } {\n const registry = useContext(InjectionContext);\n const entries = registry.get(component) ?? [];\n\n const deps = useMemo(\n () =>\n entries.length\n ? entries.flatMap((e) => e.keys.map((k) => (props as any)[k]))\n : [],\n [entries, props],\n );\n\n // Compute injected classes provided through ClassNameInjectionRegistry\n const injected = useMemo(() => {\n const { className: _ignore, ...restProps } = props as any;\n if (!entries.length) return [];\n return entries\n .map((e) => e.fn(restProps))\n .filter((v): v is string => v != null);\n }, [entries, deps, props]);\n\n // Merge original className with injected classes\n const className = useMemo(\n () => clsx((props as any).className, injected) || undefined,\n [props, injected],\n );\n\n // Create a cleaned props object by stripping keys used by injectors, to avoid DOM errors with unknown attributes\n const cleanProps = useMemo(() => {\n const { className: _ignore, ...restProps } = props as any;\n if (!entries.length) {\n return restProps as Omit<Props, \"className\">;\n }\n const copy = { ...restProps } as Omit<Props, \"className\">;\n for (const entry of entries) {\n for (const key of entry.keys) {\n if (Object.hasOwn(copy, key)) {\n delete (copy as any)[key];\n }\n }\n }\n return copy;\n }, [entries, deps, props]);\n\n return { className, props: cleanProps };\n}\n\n/**\n * Register a class injector for a supported component name.\n * - Keys must be valid string keys for that component’s props (as declared in ComponentPropsMap).\n * - Injector receives only the declared keys (Pick<PropsOf<C>, Keys>).\n */\nexport function registerClassInjector<\n Props extends Record<string, any>,\n Keys extends Extract<keyof Props, string>,\n>(\n registry: ClassNameInjectionRegistry,\n component: SupportedComponent,\n keys: Keys[],\n injector: ClassNameInjector<Props, Keys>,\n) {\n if (!registry.has(component)) {\n registry.set(component, []);\n }\n\n const wrapped = (props: Record<string, any>) => {\n const picked = Object.fromEntries(keys.map((k) => [k, props[k]])) as Pick<\n Props,\n Keys\n >;\n return injector(picked);\n };\n\n registry.get(component)!.push({\n fn: wrapped as (props: unknown) => string | undefined,\n keys: keys as string[],\n });\n}\n"],"names":["createContext","useMemo","useEffect","useContext","clsx"],"mappings":"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"}
|
package/dist-es/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { useComponentCssInjection } from './use-style-injection/useStyleInjection.js';
|
|
2
|
-
export { InsertionPointProvider, useInsertionPoint } from './use-style-injection/InsertionPointProvider.js';
|
|
3
1
|
export { StyleInjectionProvider, useStyleInjection } from './style-injection-provider/index.js';
|
|
2
|
+
export { InsertionPointProvider, useInsertionPoint } from './use-style-injection/InsertionPointProvider.js';
|
|
3
|
+
export { useComponentCssInjection } from './use-style-injection/useStyleInjection.js';
|
|
4
|
+
export { ClassNameInjectionProvider, registerClassInjector, useClassNameInjection } from './useClassNameInjection.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist-es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -4,15 +4,12 @@ import { createContext, useContext } from 'react';
|
|
|
4
4
|
const StyleInjectionContext = createContext(true);
|
|
5
5
|
function useStyleInjection(enableStyleInjection) {
|
|
6
6
|
const enableStyleInjectionFromContext = useContext(StyleInjectionContext);
|
|
7
|
-
return enableStyleInjection
|
|
7
|
+
return enableStyleInjection ?? enableStyleInjectionFromContext;
|
|
8
8
|
}
|
|
9
9
|
function StyleInjectionProvider(props) {
|
|
10
10
|
const { value: enableStyleInjectionProp, children } = props;
|
|
11
11
|
const value = useStyleInjection(enableStyleInjectionProp);
|
|
12
|
-
return /* @__PURE__ */ jsx(StyleInjectionContext.Provider, {
|
|
13
|
-
value,
|
|
14
|
-
children
|
|
15
|
-
});
|
|
12
|
+
return /* @__PURE__ */ jsx(StyleInjectionContext.Provider, { value, children });
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
export { StyleInjectionProvider, useStyleInjection };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/style-injection-provider/index.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/style-injection-provider/index.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nexport interface StyleInjectionContextType {\n value?: boolean;\n}\n\nconst StyleInjectionContext = createContext(true);\n\nexport function useStyleInjection(enableStyleInjection?: boolean): boolean {\n const enableStyleInjectionFromContext = useContext(StyleInjectionContext);\n return enableStyleInjection ?? enableStyleInjectionFromContext;\n}\n\nexport interface StyleInjectionProviderProps extends StyleInjectionContextType {\n children: ReactNode;\n}\n\nexport function StyleInjectionProvider(props: StyleInjectionProviderProps) {\n const { value: enableStyleInjectionProp, children } = props;\n const value = useStyleInjection(enableStyleInjectionProp);\n\n return (\n <StyleInjectionContext.Provider value={value}>\n {children}\n </StyleInjectionContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;AAKA,MAAM,qBAAA,GAAwB,cAAc,IAAI,CAAA;AAEzC,SAAS,kBAAkB,oBAAA,EAAyC;AACzE,EAAA,MAAM,+BAAA,GAAkC,WAAW,qBAAqB,CAAA;AACxE,EAAA,OAAO,oBAAA,IAAwB,+BAAA;AACjC;AAMO,SAAS,uBAAuB,KAAA,EAAoC;AACzE,EAAA,MAAM,EAAE,KAAA,EAAO,wBAAA,EAA0B,QAAA,EAAS,GAAI,KAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,kBAAkB,wBAAwB,CAAA;AAExD,EAAA,uBACE,GAAA,CAAC,qBAAA,CAAsB,QAAA,EAAtB,EAA+B,OAC7B,QAAA,EACH,CAAA;AAEJ;;;;"}
|
|
@@ -8,10 +8,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
8
8
|
function InsertionPointProvider(props) {
|
|
9
9
|
const { insertionPoint: insertionPointProp, children } = props;
|
|
10
10
|
const value = useMemo(() => insertionPointProp, [insertionPointProp]);
|
|
11
|
-
return /* @__PURE__ */ jsx(InsertionPointContext.Provider, {
|
|
12
|
-
value,
|
|
13
|
-
children
|
|
14
|
-
});
|
|
11
|
+
return /* @__PURE__ */ jsx(InsertionPointContext.Provider, { value, children });
|
|
15
12
|
}
|
|
16
13
|
function useInsertionPoint() {
|
|
17
14
|
const value = useContext(InsertionPointContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InsertionPointProvider.js","sources":["../src/use-style-injection/InsertionPointProvider.tsx"],"sourcesContent":["import { createContext, ReactNode, useContext, useMemo } from \"react\";\n\nexport interface InsertionPointContextType {\n insertionPoint: ChildNode | null;\n}\n\nconst InsertionPointContext = createContext<ChildNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n InsertionPointContext.displayName = \"InsertionPointContext\";\n}\n\nexport interface InsertionPointProviderProps extends InsertionPointContextType {\n children: ReactNode;\n}\n\nexport function InsertionPointProvider(props: InsertionPointProviderProps) {\n const { insertionPoint: insertionPointProp, children } = props;\n const value = useMemo(() => insertionPointProp, [insertionPointProp]);\n\n return (\n <InsertionPointContext.Provider value={value}>\n {children}\n </InsertionPointContext.Provider>\n );\n}\n\nexport function useInsertionPoint() {\n const value = useContext(InsertionPointContext);\n return value;\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,qBAAA,GAAwB,cAAgC,IAAI,CAAA
|
|
1
|
+
{"version":3,"file":"InsertionPointProvider.js","sources":["../src/use-style-injection/InsertionPointProvider.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\nexport interface InsertionPointContextType {\n insertionPoint: ChildNode | null;\n}\n\nconst InsertionPointContext = createContext<ChildNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n InsertionPointContext.displayName = \"InsertionPointContext\";\n}\n\nexport interface InsertionPointProviderProps extends InsertionPointContextType {\n children: ReactNode;\n}\n\nexport function InsertionPointProvider(props: InsertionPointProviderProps) {\n const { insertionPoint: insertionPointProp, children } = props;\n const value = useMemo(() => insertionPointProp, [insertionPointProp]);\n\n return (\n <InsertionPointContext.Provider value={value}>\n {children}\n </InsertionPointContext.Provider>\n );\n}\n\nexport function useInsertionPoint() {\n const value = useContext(InsertionPointContext);\n return value;\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,qBAAA,GAAwB,cAAgC,IAAI,CAAA;AAElE,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc;AACzC,EAAA,qBAAA,CAAsB,WAAA,GAAc,uBAAA;AACtC;AAMO,SAAS,uBAAuB,KAAA,EAAoC;AACzE,EAAA,MAAM,EAAE,cAAA,EAAgB,kBAAA,EAAoB,QAAA,EAAS,GAAI,KAAA;AACzD,EAAA,MAAM,QAAQ,OAAA,CAAQ,MAAM,kBAAA,EAAoB,CAAC,kBAAkB,CAAC,CAAA;AAEpE,EAAA,uBACE,GAAA,CAAC,qBAAA,CAAsB,QAAA,EAAtB,EAA+B,OAC7B,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,KAAA,GAAQ,WAAW,qBAAqB,CAAA;AAC9C,EAAA,OAAO,KAAA;AACT;;;;"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useInsertionPoint } from './InsertionPointProvider.js';
|
|
3
2
|
import { useStyleInjection } from '../style-injection-provider/index.js';
|
|
3
|
+
import { useInsertionPoint } from './InsertionPointProvider.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const maybeUseInsertionEffect = (
|
|
6
|
+
// biome-ignore lint/suspicious/noExplicitAny: see comment above
|
|
7
|
+
React["useInsertionEffect".toString()] ?? React.useLayoutEffect
|
|
8
|
+
);
|
|
7
9
|
const windowSheetsMap = /* @__PURE__ */ new WeakMap();
|
|
8
10
|
function useComponentCssInjection({
|
|
9
11
|
testId,
|
|
@@ -13,12 +15,11 @@ function useComponentCssInjection({
|
|
|
13
15
|
const styleInjectionEnabled = useStyleInjection();
|
|
14
16
|
const insertionPoint = useInsertionPoint();
|
|
15
17
|
maybeUseInsertionEffect(() => {
|
|
16
|
-
var _a2, _b;
|
|
17
18
|
if (!targetWindow || !styleInjectionEnabled) {
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
|
-
const sheetsMap =
|
|
21
|
-
const styleMap =
|
|
21
|
+
const sheetsMap = windowSheetsMap.get(targetWindow) ?? /* @__PURE__ */ new Map();
|
|
22
|
+
const styleMap = sheetsMap.get(css) ?? { styleElement: null, count: 0 };
|
|
22
23
|
if (styleMap.styleElement == null) {
|
|
23
24
|
styleMap.styleElement = targetWindow.document.createElement("style");
|
|
24
25
|
styleMap.styleElement.setAttribute("type", "text/css");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStyleInjection.js","sources":["../src/use-style-injection/useStyleInjection.ts"],"sourcesContent":["import * as React from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"useStyleInjection.js","sources":["../src/use-style-injection/useStyleInjection.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useStyleInjection } from \"../style-injection-provider\";\nimport { useInsertionPoint } from \"./InsertionPointProvider\";\n\n/* Workaround for https://github.com/webpack/webpack/issues/14814#issuecomment-1536757985 */\nconst maybeUseInsertionEffect: typeof React.useLayoutEffect =\n // biome-ignore lint/suspicious/noExplicitAny: see comment above\n (React as any)[\"useInsertionEffect\".toString()] ?? React.useLayoutEffect;\n\nexport interface UseComponentCssInjection {\n testId?: string;\n css: string;\n window?: Window | null;\n}\n\ntype StyleElementMap = Map<\n string,\n { styleElement: HTMLStyleElement | null; count: number }\n>;\n\n// windowSheetsMap maps window objects to StyleElementMaps\n// A StyleElementMap maps css strings to style element tags\nconst windowSheetsMap = new WeakMap<Window, StyleElementMap>();\n\nexport function useComponentCssInjection({\n testId,\n css,\n window: targetWindow,\n}: UseComponentCssInjection): void {\n const styleInjectionEnabled = useStyleInjection();\n const insertionPoint = useInsertionPoint();\n\n maybeUseInsertionEffect(() => {\n if (!targetWindow || !styleInjectionEnabled) {\n return;\n }\n\n const sheetsMap =\n windowSheetsMap.get(targetWindow) ??\n new Map<\n string,\n { styleElement: HTMLStyleElement | null; count: number }\n >();\n const styleMap = sheetsMap.get(css) ?? { styleElement: null, count: 0 };\n\n if (styleMap.styleElement == null) {\n styleMap.styleElement = targetWindow.document.createElement(\"style\");\n styleMap.styleElement.setAttribute(\"type\", \"text/css\");\n styleMap.styleElement.setAttribute(\"data-salt-style\", testId || \"\");\n styleMap.styleElement.textContent = css;\n\n styleMap.count = 1;\n\n targetWindow.document.head.insertBefore(\n styleMap.styleElement,\n insertionPoint || targetWindow.document.head.firstChild,\n );\n } else {\n styleMap.styleElement.textContent = css;\n styleMap.count++;\n }\n sheetsMap.set(css, styleMap);\n windowSheetsMap.set(targetWindow, sheetsMap);\n\n return () => {\n const sheetsMap = windowSheetsMap.get(targetWindow);\n const styleMap = sheetsMap?.get(css);\n if (styleMap?.styleElement) {\n styleMap.count--;\n if (styleMap.count < 1) {\n targetWindow.document.head.removeChild(styleMap.styleElement);\n styleMap.styleElement = null;\n sheetsMap?.delete(css);\n }\n }\n };\n }, [testId, css, targetWindow]);\n}\n"],"names":["sheetsMap","styleMap"],"mappings":";;;;AAKA,MAAM,uBAAA;AAAA;AAAA,EAEH,KAAA,CAAc,oBAAA,CAAqB,QAAA,EAAU,KAAK,KAAA,CAAM;AAAA,CAAA;AAe3D,MAAM,eAAA,uBAAsB,OAAA,EAAiC;AAEtD,SAAS,wBAAA,CAAyB;AAAA,EACvC,MAAA;AAAA,EACA,GAAA;AAAA,EACA,MAAA,EAAQ;AACV,CAAA,EAAmC;AACjC,EAAA,MAAM,wBAAwB,iBAAA,EAAkB;AAChD,EAAA,MAAM,iBAAiB,iBAAA,EAAkB;AAEzC,EAAA,uBAAA,CAAwB,MAAM;AAC5B,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,qBAAA,EAAuB;AAC3C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YACJ,eAAA,CAAgB,GAAA,CAAI,YAAY,CAAA,wBAC5B,GAAA,EAGF;AACJ,IAAA,MAAM,QAAA,GAAW,UAAU,GAAA,CAAI,GAAG,KAAK,EAAE,YAAA,EAAc,IAAA,EAAM,KAAA,EAAO,CAAA,EAAE;AAEtE,IAAA,IAAI,QAAA,CAAS,gBAAgB,IAAA,EAAM;AACjC,MAAA,QAAA,CAAS,YAAA,GAAe,YAAA,CAAa,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AACnE,MAAA,QAAA,CAAS,YAAA,CAAa,YAAA,CAAa,MAAA,EAAQ,UAAU,CAAA;AACrD,MAAA,QAAA,CAAS,YAAA,CAAa,YAAA,CAAa,iBAAA,EAAmB,MAAA,IAAU,EAAE,CAAA;AAClE,MAAA,QAAA,CAAS,aAAa,WAAA,GAAc,GAAA;AAEpC,MAAA,QAAA,CAAS,KAAA,GAAQ,CAAA;AAEjB,MAAA,YAAA,CAAa,SAAS,IAAA,CAAK,YAAA;AAAA,QACzB,QAAA,CAAS,YAAA;AAAA,QACT,cAAA,IAAkB,YAAA,CAAa,QAAA,CAAS,IAAA,CAAK;AAAA,OAC/C;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,aAAa,WAAA,GAAc,GAAA;AACpC,MAAA,QAAA,CAAS,KAAA,EAAA;AAAA,IACX;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,KAAK,QAAQ,CAAA;AAC3B,IAAA,eAAA,CAAgB,GAAA,CAAI,cAAc,SAAS,CAAA;AAE3C,IAAA,OAAO,MAAM;AACX,MAAA,MAAMA,UAAAA,GAAY,eAAA,CAAgB,GAAA,CAAI,YAAY,CAAA;AAClD,MAAA,MAAMC,SAAAA,GAAWD,UAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,UAAAA,CAAW,GAAA,CAAI,GAAA,CAAA;AAChC,MAAA,IAAIC,SAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,SAAAA,CAAU,YAAA,EAAc;AAC1B,QAAAA,SAAAA,CAAS,KAAA,EAAA;AACT,QAAA,IAAIA,SAAAA,CAAS,QAAQ,CAAA,EAAG;AACtB,UAAA,YAAA,CAAa,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYA,SAAAA,CAAS,YAAY,CAAA;AAC5D,UAAAA,UAAS,YAAA,GAAe,IAAA;AACxB,UAAAD,UAAAA,IAAA,IAAA,GAAA,MAAA,GAAAA,UAAAA,CAAW,MAAA,CAAO,GAAA,CAAA;AAAA,QACpB;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,GAAA,EAAK,YAAY,CAAC,CAAA;AAChC;;;;"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { createContext, useMemo, useEffect, useContext } from 'react';
|
|
4
|
+
|
|
5
|
+
const EMPTY_REGISTRY = /* @__PURE__ */ new Map();
|
|
6
|
+
const InjectionContext = createContext(EMPTY_REGISTRY);
|
|
7
|
+
let hasWarnedExperimentalOnce = false;
|
|
8
|
+
function ClassNameInjectionProvider({
|
|
9
|
+
children,
|
|
10
|
+
value
|
|
11
|
+
}) {
|
|
12
|
+
const registry = useMemo(() => value ?? EMPTY_REGISTRY, [value]);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!hasWarnedExperimentalOnce && process.env.NODE_ENV !== "production") {
|
|
15
|
+
console.warn(
|
|
16
|
+
"Salt ClassNameInjectionProvider is experimental and subject to change. JPM users: only recommended in non-production environments or with prior permission from the Salt team."
|
|
17
|
+
);
|
|
18
|
+
hasWarnedExperimentalOnce = true;
|
|
19
|
+
}
|
|
20
|
+
}, []);
|
|
21
|
+
return /* @__PURE__ */ jsx(InjectionContext.Provider, { value: registry, children });
|
|
22
|
+
}
|
|
23
|
+
function useClassNameInjection(component, props) {
|
|
24
|
+
const registry = useContext(InjectionContext);
|
|
25
|
+
const entries = registry.get(component) ?? [];
|
|
26
|
+
const deps = useMemo(
|
|
27
|
+
() => entries.length ? entries.flatMap((e) => e.keys.map((k) => props[k])) : [],
|
|
28
|
+
[entries, props]
|
|
29
|
+
);
|
|
30
|
+
const injected = useMemo(() => {
|
|
31
|
+
const { className: _ignore, ...restProps } = props;
|
|
32
|
+
if (!entries.length) return [];
|
|
33
|
+
return entries.map((e) => e.fn(restProps)).filter((v) => v != null);
|
|
34
|
+
}, [entries, deps, props]);
|
|
35
|
+
const className = useMemo(
|
|
36
|
+
() => clsx(props.className, injected) || void 0,
|
|
37
|
+
[props, injected]
|
|
38
|
+
);
|
|
39
|
+
const cleanProps = useMemo(() => {
|
|
40
|
+
const { className: _ignore, ...restProps } = props;
|
|
41
|
+
if (!entries.length) {
|
|
42
|
+
return restProps;
|
|
43
|
+
}
|
|
44
|
+
const copy = { ...restProps };
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
for (const key of entry.keys) {
|
|
47
|
+
if (Object.hasOwn(copy, key)) {
|
|
48
|
+
delete copy[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return copy;
|
|
53
|
+
}, [entries, deps, props]);
|
|
54
|
+
return { className, props: cleanProps };
|
|
55
|
+
}
|
|
56
|
+
function registerClassInjector(registry, component, keys, injector) {
|
|
57
|
+
if (!registry.has(component)) {
|
|
58
|
+
registry.set(component, []);
|
|
59
|
+
}
|
|
60
|
+
const wrapped = (props) => {
|
|
61
|
+
const picked = Object.fromEntries(keys.map((k) => [k, props[k]]));
|
|
62
|
+
return injector(picked);
|
|
63
|
+
};
|
|
64
|
+
registry.get(component).push({
|
|
65
|
+
fn: wrapped,
|
|
66
|
+
keys
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { ClassNameInjectionProvider, registerClassInjector, useClassNameInjection };
|
|
71
|
+
//# sourceMappingURL=useClassNameInjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useClassNameInjection.js","sources":["../src/useClassNameInjection.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n} from \"react\";\n\n/**\n * Extensible map of supported components → their props.\n * @salt-ds/core must augment this with the components that support the API,\n * using the same key string that the component passes to useClassNameInjection,\n * e.g., \"saltButton\": ButtonProps.\n */\nexport interface ComponentPropsMap {}\n\ntype SupportedComponent = keyof ComponentPropsMap extends never\n ? \"ComponentPropsMap must be augmented to define the components that support useClassNameInjection\"\n : keyof ComponentPropsMap;\n\nexport type ClassNameInjector<Props, Keys extends keyof Props> = (\n props: Pick<Props, Keys>,\n) => string | undefined;\n\ninterface ClassNameInjectorEntry {\n fn: (props: unknown) => string | undefined;\n keys: string[];\n}\n\nexport type ClassNameInjectionRegistry<\n ComponentName extends SupportedComponent = SupportedComponent,\n> = Map<ComponentName, ClassNameInjectorEntry[]>;\n\nconst EMPTY_REGISTRY: ClassNameInjectionRegistry = new Map();\nconst InjectionContext =\n createContext<ClassNameInjectionRegistry>(EMPTY_REGISTRY);\n\nexport type ClassNameInjectionProviderProps = {\n children: ReactNode;\n value?: ClassNameInjectionRegistry;\n};\n\nlet hasWarnedExperimentalOnce = false;\n\nexport function ClassNameInjectionProvider({\n children,\n value,\n}: ClassNameInjectionProviderProps) {\n const registry = useMemo(() => value ?? EMPTY_REGISTRY, [value]);\n\n useEffect(() => {\n if (!hasWarnedExperimentalOnce && process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"Salt ClassNameInjectionProvider is experimental and subject to change. JPM users: only recommended in non-production environments or with prior permission from the Salt team.\",\n );\n hasWarnedExperimentalOnce = true;\n }\n }, []);\n\n return (\n <InjectionContext.Provider value={registry}>\n {children}\n </InjectionContext.Provider>\n );\n}\n\ntype PropsWithClassName = { className?: string } & Record<string, any>;\n\n/**\n * Return the className created by the registry and a props object with injector keys stripped.\n * Only components declared in ComponentPropsMap can call this at compile time.\n */\nexport function useClassNameInjection<Props extends PropsWithClassName>(\n component: SupportedComponent,\n props: Props,\n): { className: string | undefined; props: Omit<Props, \"className\"> } {\n const registry = useContext(InjectionContext);\n const entries = registry.get(component) ?? [];\n\n const deps = useMemo(\n () =>\n entries.length\n ? entries.flatMap((e) => e.keys.map((k) => (props as any)[k]))\n : [],\n [entries, props],\n );\n\n // Compute injected classes provided through ClassNameInjectionRegistry\n const injected = useMemo(() => {\n const { className: _ignore, ...restProps } = props as any;\n if (!entries.length) return [];\n return entries\n .map((e) => e.fn(restProps))\n .filter((v): v is string => v != null);\n }, [entries, deps, props]);\n\n // Merge original className with injected classes\n const className = useMemo(\n () => clsx((props as any).className, injected) || undefined,\n [props, injected],\n );\n\n // Create a cleaned props object by stripping keys used by injectors, to avoid DOM errors with unknown attributes\n const cleanProps = useMemo(() => {\n const { className: _ignore, ...restProps } = props as any;\n if (!entries.length) {\n return restProps as Omit<Props, \"className\">;\n }\n const copy = { ...restProps } as Omit<Props, \"className\">;\n for (const entry of entries) {\n for (const key of entry.keys) {\n if (Object.hasOwn(copy, key)) {\n delete (copy as any)[key];\n }\n }\n }\n return copy;\n }, [entries, deps, props]);\n\n return { className, props: cleanProps };\n}\n\n/**\n * Register a class injector for a supported component name.\n * - Keys must be valid string keys for that component’s props (as declared in ComponentPropsMap).\n * - Injector receives only the declared keys (Pick<PropsOf<C>, Keys>).\n */\nexport function registerClassInjector<\n Props extends Record<string, any>,\n Keys extends Extract<keyof Props, string>,\n>(\n registry: ClassNameInjectionRegistry,\n component: SupportedComponent,\n keys: Keys[],\n injector: ClassNameInjector<Props, Keys>,\n) {\n if (!registry.has(component)) {\n registry.set(component, []);\n }\n\n const wrapped = (props: Record<string, any>) => {\n const picked = Object.fromEntries(keys.map((k) => [k, props[k]])) as Pick<\n Props,\n Keys\n >;\n return injector(picked);\n };\n\n registry.get(component)!.push({\n fn: wrapped as (props: unknown) => string | undefined,\n keys: keys as string[],\n });\n}\n"],"names":[],"mappings":"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"}
|
package/dist-types/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export declare function useStyleInjection(enableStyleInjection?: boolean): boole
|
|
|
6
6
|
export interface StyleInjectionProviderProps extends StyleInjectionContextType {
|
|
7
7
|
children: ReactNode;
|
|
8
8
|
}
|
|
9
|
-
export declare function StyleInjectionProvider(props: StyleInjectionProviderProps): JSX.Element;
|
|
9
|
+
export declare function StyleInjectionProvider(props: StyleInjectionProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
2
|
export interface InsertionPointContextType {
|
|
3
3
|
insertionPoint: ChildNode | null;
|
|
4
4
|
}
|
|
5
5
|
export interface InsertionPointProviderProps extends InsertionPointContextType {
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
}
|
|
8
|
-
export declare function InsertionPointProvider(props: InsertionPointProviderProps): JSX.Element;
|
|
8
|
+
export declare function InsertionPointProvider(props: InsertionPointProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
export declare function useInsertionPoint(): ChildNode | null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Extensible map of supported components → their props.
|
|
4
|
+
* @salt-ds/core must augment this with the components that support the API,
|
|
5
|
+
* using the same key string that the component passes to useClassNameInjection,
|
|
6
|
+
* e.g., "saltButton": ButtonProps.
|
|
7
|
+
*/
|
|
8
|
+
export interface ComponentPropsMap {
|
|
9
|
+
}
|
|
10
|
+
type SupportedComponent = keyof ComponentPropsMap extends never ? "ComponentPropsMap must be augmented to define the components that support useClassNameInjection" : keyof ComponentPropsMap;
|
|
11
|
+
export type ClassNameInjector<Props, Keys extends keyof Props> = (props: Pick<Props, Keys>) => string | undefined;
|
|
12
|
+
interface ClassNameInjectorEntry {
|
|
13
|
+
fn: (props: unknown) => string | undefined;
|
|
14
|
+
keys: string[];
|
|
15
|
+
}
|
|
16
|
+
export type ClassNameInjectionRegistry<ComponentName extends SupportedComponent = SupportedComponent> = Map<ComponentName, ClassNameInjectorEntry[]>;
|
|
17
|
+
export type ClassNameInjectionProviderProps = {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
value?: ClassNameInjectionRegistry;
|
|
20
|
+
};
|
|
21
|
+
export declare function ClassNameInjectionProvider({ children, value, }: ClassNameInjectionProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
type PropsWithClassName = {
|
|
23
|
+
className?: string;
|
|
24
|
+
} & Record<string, any>;
|
|
25
|
+
/**
|
|
26
|
+
* Return the className created by the registry and a props object with injector keys stripped.
|
|
27
|
+
* Only components declared in ComponentPropsMap can call this at compile time.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useClassNameInjection<Props extends PropsWithClassName>(component: SupportedComponent, props: Props): {
|
|
30
|
+
className: string | undefined;
|
|
31
|
+
props: Omit<Props, "className">;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Register a class injector for a supported component name.
|
|
35
|
+
* - Keys must be valid string keys for that component’s props (as declared in ComponentPropsMap).
|
|
36
|
+
* - Injector receives only the declared keys (Pick<PropsOf<C>, Keys>).
|
|
37
|
+
*/
|
|
38
|
+
export declare function registerClassInjector<Props extends Record<string, any>, Keys extends Extract<keyof Props, string>>(registry: ClassNameInjectionRegistry, component: SupportedComponent, keys: Keys[], injector: ClassNameInjector<Props, Keys>): void;
|
|
39
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salt-ds/styles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/jpmorganchase/salt-ds.git",
|
|
7
|
+
"url": "git+https://github.com/jpmorganchase/salt-ds.git",
|
|
8
8
|
"directory": "packages/styles"
|
|
9
9
|
},
|
|
10
10
|
"bugs": "https://github.com/jpmorganchase/salt-ds/issues",
|
|
@@ -24,13 +24,16 @@
|
|
|
24
24
|
"directory": "../../dist/salt-ds-styles",
|
|
25
25
|
"provenance": true
|
|
26
26
|
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "yarn node ../../scripts/build.mjs"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {},
|
|
27
31
|
"module": "dist-es/index.js",
|
|
28
32
|
"typings": "dist-types/index.d.ts",
|
|
29
|
-
"dependencies": {},
|
|
30
33
|
"files": [
|
|
31
34
|
"dist-cjs",
|
|
32
35
|
"dist-es",
|
|
33
36
|
"dist-types",
|
|
34
|
-
"
|
|
37
|
+
"CHANGELOG.md"
|
|
35
38
|
]
|
|
36
39
|
}
|