@plantops/ui 0.1.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.
Files changed (63) hide show
  1. package/README.md +74 -0
  2. package/dist/data/data-table.d.ts +41 -0
  3. package/dist/data/data-table.d.ts.map +1 -0
  4. package/dist/data/data-table.js +31 -0
  5. package/dist/data/scope-tree-select.d.ts +51 -0
  6. package/dist/data/scope-tree-select.d.ts.map +1 -0
  7. package/dist/data/scope-tree-select.js +59 -0
  8. package/dist/data/scope-tree.d.ts +127 -0
  9. package/dist/data/scope-tree.d.ts.map +1 -0
  10. package/dist/data/scope-tree.js +163 -0
  11. package/dist/data/status-tag.d.ts +14 -0
  12. package/dist/data/status-tag.d.ts.map +1 -0
  13. package/dist/data/status-tag.js +50 -0
  14. package/dist/feedback/error-copy.d.ts +38 -0
  15. package/dist/feedback/error-copy.d.ts.map +1 -0
  16. package/dist/feedback/error-copy.js +97 -0
  17. package/dist/feedback/page-header.d.ts +17 -0
  18. package/dist/feedback/page-header.d.ts.map +1 -0
  19. package/dist/feedback/page-header.js +23 -0
  20. package/dist/feedback/state-panels.d.ts +50 -0
  21. package/dist/feedback/state-panels.d.ts.map +1 -0
  22. package/dist/feedback/state-panels.js +46 -0
  23. package/dist/forms/auth-layout.d.ts +12 -0
  24. package/dist/forms/auth-layout.d.ts.map +1 -0
  25. package/dist/forms/auth-layout.js +28 -0
  26. package/dist/forms/credentials-form.d.ts +34 -0
  27. package/dist/forms/credentials-form.d.ts.map +1 -0
  28. package/dist/forms/credentials-form.js +37 -0
  29. package/dist/icons/icon-registry.d.ts +25 -0
  30. package/dist/icons/icon-registry.d.ts.map +1 -0
  31. package/dist/icons/icon-registry.js +102 -0
  32. package/dist/index.d.ts +52 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +51 -0
  35. package/dist/layout/app-shell.d.ts +23 -0
  36. package/dist/layout/app-shell.d.ts.map +1 -0
  37. package/dist/layout/app-shell.js +84 -0
  38. package/dist/layout/brand.d.ts +10 -0
  39. package/dist/layout/brand.d.ts.map +1 -0
  40. package/dist/layout/brand.js +48 -0
  41. package/dist/layout/nav-menu.d.ts +30 -0
  42. package/dist/layout/nav-menu.d.ts.map +1 -0
  43. package/dist/layout/nav-menu.js +75 -0
  44. package/dist/layout/nav-tree.d.ts +67 -0
  45. package/dist/layout/nav-tree.d.ts.map +1 -0
  46. package/dist/layout/nav-tree.js +101 -0
  47. package/dist/layout/user-menu.d.ts +20 -0
  48. package/dist/layout/user-menu.d.ts.map +1 -0
  49. package/dist/layout/user-menu.js +75 -0
  50. package/dist/theme/color-mode.d.ts +45 -0
  51. package/dist/theme/color-mode.d.ts.map +1 -0
  52. package/dist/theme/color-mode.js +81 -0
  53. package/dist/theme/theme-provider.d.ts +17 -0
  54. package/dist/theme/theme-provider.d.ts.map +1 -0
  55. package/dist/theme/theme-provider.js +65 -0
  56. package/dist/theme/theme.d.ts +23 -0
  57. package/dist/theme/theme.d.ts.map +1 -0
  58. package/dist/theme/theme.js +141 -0
  59. package/dist/theme/tokens.d.ts +130 -0
  60. package/dist/theme/tokens.d.ts.map +1 -0
  61. package/dist/theme/tokens.js +127 -0
  62. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  63. package/package.json +48 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Which colour mode is showing, and how a user changes it.
3
+ *
4
+ * Split out of {@link PlantOpsThemeProvider} because the header's toggle needs
5
+ * to *set* the mode from far below the provider that applies it, and a context
6
+ * is the only way to do that without every shell prop-drilling a setter it does
7
+ * not otherwise care about.
8
+ *
9
+ * ## Hydration
10
+ *
11
+ * The stored preference lives in `localStorage`, which the server cannot read —
12
+ * so the first render always uses `defaultMode` and the stored value is adopted
13
+ * in an effect. Rendering the stored mode directly would produce server HTML
14
+ * that disagrees with the first client render, and React would discard the
15
+ * whole tree. The visible cost is one frame in the default mode on a hard
16
+ * reload; consumers that mind can inline a blocking script that sets the
17
+ * preference before paint and pass it as `defaultMode`.
18
+ */
19
+ import * as React from 'react';
20
+ import type { ColorMode } from './tokens';
21
+ /** Where the preference is kept. Shared by every PlantOps console on the host. */
22
+ export declare const COLOR_MODE_STORAGE_KEY = "plantops.color-mode";
23
+ export interface ColorModeContextValue {
24
+ mode: ColorMode;
25
+ setMode: (mode: ColorMode) => void;
26
+ toggle: () => void;
27
+ }
28
+ /**
29
+ * The current colour mode.
30
+ *
31
+ * Throws outside a {@link PlantOpsThemeProvider} rather than defaulting to
32
+ * light: a silent default would render a toggle that appears to work and
33
+ * changes nothing.
34
+ */
35
+ export declare function useColorMode(): ColorModeContextValue;
36
+ export interface ColorModeProviderProps {
37
+ children: React.ReactNode;
38
+ /** What renders before the stored preference is known. Default `'light'`. */
39
+ defaultMode?: ColorMode;
40
+ /** Override to give an app its own preference slot. */
41
+ storageKey?: string;
42
+ }
43
+ /** Supplies {@link useColorMode}. {@link PlantOpsThemeProvider} includes one. */
44
+ export declare function ColorModeProvider({ children, defaultMode, storageKey, }: ColorModeProviderProps): React.ReactElement;
45
+ //# sourceMappingURL=color-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-mode.d.ts","sourceRoot":"","sources":["../../src/theme/color-mode.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,wBAAwB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,qBAAqB,CAQpD;AA2BD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,WAAqB,EACrB,UAAmC,GACpC,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CA4B7C"}
@@ -0,0 +1,81 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Which colour mode is showing, and how a user changes it.
5
+ *
6
+ * Split out of {@link PlantOpsThemeProvider} because the header's toggle needs
7
+ * to *set* the mode from far below the provider that applies it, and a context
8
+ * is the only way to do that without every shell prop-drilling a setter it does
9
+ * not otherwise care about.
10
+ *
11
+ * ## Hydration
12
+ *
13
+ * The stored preference lives in `localStorage`, which the server cannot read —
14
+ * so the first render always uses `defaultMode` and the stored value is adopted
15
+ * in an effect. Rendering the stored mode directly would produce server HTML
16
+ * that disagrees with the first client render, and React would discard the
17
+ * whole tree. The visible cost is one frame in the default mode on a hard
18
+ * reload; consumers that mind can inline a blocking script that sets the
19
+ * preference before paint and pass it as `defaultMode`.
20
+ */
21
+ import * as React from 'react';
22
+ /** Where the preference is kept. Shared by every PlantOps console on the host. */
23
+ export const COLOR_MODE_STORAGE_KEY = 'plantops.color-mode';
24
+ const ColorModeContext = React.createContext(null);
25
+ /**
26
+ * The current colour mode.
27
+ *
28
+ * Throws outside a {@link PlantOpsThemeProvider} rather than defaulting to
29
+ * light: a silent default would render a toggle that appears to work and
30
+ * changes nothing.
31
+ */
32
+ export function useColorMode() {
33
+ const value = React.useContext(ColorModeContext);
34
+ if (value === null) {
35
+ throw new Error('useColorMode() requires a <PlantOpsThemeProvider> above it in the tree.');
36
+ }
37
+ return value;
38
+ }
39
+ function isColorMode(value) {
40
+ return value === 'light' || value === 'dark';
41
+ }
42
+ /** Reads the persisted preference, tolerating storage being unavailable. */
43
+ function readStoredMode(storageKey) {
44
+ try {
45
+ const stored = globalThis.localStorage?.getItem(storageKey);
46
+ return isColorMode(stored) ? stored : null;
47
+ }
48
+ catch {
49
+ // Private-mode Safari and locked-down enterprise policies both throw on
50
+ // access rather than returning null. A theme preference is not worth an
51
+ // error boundary.
52
+ return null;
53
+ }
54
+ }
55
+ function writeStoredMode(storageKey, mode) {
56
+ try {
57
+ globalThis.localStorage?.setItem(storageKey, mode);
58
+ }
59
+ catch {
60
+ /* see readStoredMode */
61
+ }
62
+ }
63
+ /** Supplies {@link useColorMode}. {@link PlantOpsThemeProvider} includes one. */
64
+ export function ColorModeProvider({ children, defaultMode = 'light', storageKey = COLOR_MODE_STORAGE_KEY, }) {
65
+ const [mode, setModeState] = React.useState(defaultMode);
66
+ React.useEffect(() => {
67
+ const stored = readStoredMode(storageKey);
68
+ if (stored !== null)
69
+ setModeState(stored);
70
+ }, [storageKey]);
71
+ const setMode = React.useCallback((next) => {
72
+ setModeState(next);
73
+ writeStoredMode(storageKey, next);
74
+ }, [storageKey]);
75
+ const value = React.useMemo(() => ({
76
+ mode,
77
+ setMode,
78
+ toggle: () => setMode(mode === 'dark' ? 'light' : 'dark'),
79
+ }), [mode, setMode]);
80
+ return (_jsx(ColorModeContext.Provider, { value: value, children: children }));
81
+ }
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import type { ColorMode } from './tokens';
3
+ export interface PlantOpsThemeProviderProps {
4
+ children: React.ReactNode;
5
+ /**
6
+ * Fixes the colour mode and disables the internal preference store — for a
7
+ * consumer whose mode comes from elsewhere (a user profile, an OS media
8
+ * query it already watches). Omit for the normal, self-managing behaviour.
9
+ */
10
+ mode?: ColorMode;
11
+ /** Initial mode before a stored preference is read. Default `'light'`. */
12
+ defaultMode?: ColorMode;
13
+ /** `localStorage` slot for the preference. */
14
+ storageKey?: string;
15
+ }
16
+ export declare function PlantOpsThemeProvider({ children, mode, defaultMode, storageKey, }: PlantOpsThemeProviderProps): React.ReactElement;
17
+ //# sourceMappingURL=theme-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,UAAU,GACX,EAAE,0BAA0B,GAAG,KAAK,CAAC,YAAY,CASjD"}
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * The one provider every PlantOps console mounts at its root.
5
+ *
6
+ * Three things it does, each of which is a bug if an app forgets it:
7
+ *
8
+ * 1. **`ConfigProvider`** applies {@link plantOpsTheme}, so the app looks like
9
+ * PlantOps rather than like default antd.
10
+ * 2. **`App`** supplies the `message`/`notification`/`modal` *hooks*. antd's
11
+ * static `message.error(…)` renders outside the React tree and therefore
12
+ * outside the theme — it comes out unstyled and, in dark mode, illegible.
13
+ * Everything in this library and in `@plantops/web-kit` reaches feedback
14
+ * through `App.useApp()`, which only works with this component mounted.
15
+ * 3. A **root surface**: `body` gets the layout background and the base text
16
+ * colour, which antd itself does not set.
17
+ *
18
+ * `ColorModeProvider` is included so that a consumer mounts one component
19
+ * rather than remembering the order of two. An app that already has its own
20
+ * colour-mode source can pass `mode` and skip it.
21
+ */
22
+ import { App as AntApp, ConfigProvider } from 'antd';
23
+ import * as React from 'react';
24
+ import { ColorModeProvider, useColorMode } from './color-mode';
25
+ import { plantOpsTheme } from './theme';
26
+ export function PlantOpsThemeProvider({ children, mode, defaultMode, storageKey, }) {
27
+ if (mode !== undefined) {
28
+ return _jsx(ThemedApp, { mode: mode, children: children });
29
+ }
30
+ return (_jsx(ColorModeProvider, { defaultMode: defaultMode, storageKey: storageKey, children: _jsx(ThemedAppFromContext, { children: children }) }));
31
+ }
32
+ function ThemedAppFromContext({ children, }) {
33
+ const { mode } = useColorMode();
34
+ return _jsx(ThemedApp, { mode: mode, children: children });
35
+ }
36
+ function ThemedApp({ mode, children, }) {
37
+ const theme = React.useMemo(() => plantOpsTheme(mode), [mode]);
38
+ return (_jsx(ConfigProvider, { theme: theme, children: _jsx(AntApp
39
+ // Room for the fixed header, so a toast never lands on top of the
40
+ // navigation the user is trying to click.
41
+ , {
42
+ // Room for the fixed header, so a toast never lands on top of the
43
+ // navigation the user is trying to click.
44
+ message: { top: 72, maxCount: 3 }, notification: { placement: 'topRight', top: 72 }, style: { minHeight: '100%' }, children: _jsx(RootSurface, { children: children }) }) }));
45
+ }
46
+ /**
47
+ * Paints `body` from the active theme.
48
+ *
49
+ * A `<style>` element rather than a wrapper `div` because the background has to
50
+ * reach the document element: overscroll, and any fixed-position overlay antd
51
+ * portals into `body`, both show whatever is behind the React root.
52
+ */
53
+ function RootSurface({ children, }) {
54
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
55
+ html, body { height: 100%; }
56
+ body {
57
+ margin: 0;
58
+ background: var(--ant-color-bg-layout);
59
+ color: var(--ant-color-text);
60
+ font-family: var(--ant-font-family);
61
+ -webkit-font-smoothing: antialiased;
62
+ }
63
+ *, *::before, *::after { box-sizing: border-box; }
64
+ ` }), children] }));
65
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The design language of `tokens.ts`, expressed as Ant Design theme configs.
3
+ *
4
+ * One place decides what antd looks like across every PlantOps console. A
5
+ * screen that needs a colour asks antd for its token (`theme.useToken()`) or
6
+ * imports from `tokens.ts`; it never writes a hex literal, because the value
7
+ * that is correct in light mode is wrong in dark mode and a literal cannot know
8
+ * which one is showing.
9
+ *
10
+ * ## Why `cssVar` is on
11
+ *
12
+ * With CSS-variable mode antd emits `--ant-color-primary: …` once and every
13
+ * component references the variable, so switching colour mode re-paints from a
14
+ * single `:root` rule instead of re-serialising the whole style sheet. That is
15
+ * what makes the mode toggle instant, and it also keeps the server-rendered
16
+ * style payload small — which matters because these consoles are Next.js apps
17
+ * that ship their antd styles from the server on first paint.
18
+ */
19
+ import type { ThemeConfig } from 'antd';
20
+ import { type ColorMode } from './tokens';
21
+ /** The antd theme for a colour mode. The only way to obtain one. */
22
+ export declare function plantOpsTheme(mode: ColorMode): ThemeConfig;
23
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/theme/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAGxC,OAAO,EACL,KAAK,SAAS,EASf,MAAM,UAAU,CAAC;AA+HlB,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAE1D"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * The design language of `tokens.ts`, expressed as Ant Design theme configs.
3
+ *
4
+ * One place decides what antd looks like across every PlantOps console. A
5
+ * screen that needs a colour asks antd for its token (`theme.useToken()`) or
6
+ * imports from `tokens.ts`; it never writes a hex literal, because the value
7
+ * that is correct in light mode is wrong in dark mode and a literal cannot know
8
+ * which one is showing.
9
+ *
10
+ * ## Why `cssVar` is on
11
+ *
12
+ * With CSS-variable mode antd emits `--ant-color-primary: …` once and every
13
+ * component references the variable, so switching colour mode re-paints from a
14
+ * single `:root` rule instead of re-serialising the whole style sheet. That is
15
+ * what makes the mode toggle instant, and it also keeps the server-rendered
16
+ * style payload small — which matters because these consoles are Next.js apps
17
+ * that ship their antd styles from the server on first paint.
18
+ */
19
+ import { theme as antdTheme } from 'antd';
20
+ import { layout, navSurface, neutral, palette, radius, shadow, spacing, typography, } from './tokens';
21
+ /** Tokens that are the same in both modes: type, rhythm, geometry. */
22
+ const sharedTokens = {
23
+ colorPrimary: palette.primary,
24
+ colorInfo: palette.info,
25
+ colorSuccess: palette.success,
26
+ colorWarning: palette.warning,
27
+ colorError: palette.error,
28
+ fontFamily: typography.fontFamily,
29
+ fontFamilyCode: typography.fontFamilyMono,
30
+ fontSize: typography.fontSize,
31
+ fontSizeSM: typography.fontSizeSm,
32
+ fontSizeLG: typography.fontSizeLg,
33
+ borderRadius: radius.md,
34
+ borderRadiusSM: radius.sm,
35
+ borderRadiusLG: radius.lg,
36
+ controlHeight: 36,
37
+ padding: spacing.md,
38
+ margin: spacing.md,
39
+ wireframe: false,
40
+ };
41
+ /**
42
+ * Component overrides shared by both modes.
43
+ *
44
+ * Kept to the handful of places where antd's default is wrong *for this
45
+ * product* rather than merely different from someone's taste: denser tables
46
+ * because these screens list hundreds of users, a flat navigation surface
47
+ * because the sidebar supplies its own colours, and a Layout whose header does
48
+ * not fight the content for attention.
49
+ */
50
+ const sharedComponents = {
51
+ Layout: {
52
+ headerHeight: layout.headerHeight,
53
+ headerPadding: `0 ${spacing.lg}px`,
54
+ siderBg: navSurface.background,
55
+ triggerBg: navSurface.backgroundHover,
56
+ triggerColor: navSurface.text,
57
+ },
58
+ Menu: {
59
+ itemHeight: 38,
60
+ itemMarginInline: spacing.xs,
61
+ itemBorderRadius: radius.md,
62
+ // The sidebar keeps its dark surface in both colour modes (see tokens.ts).
63
+ darkItemBg: 'transparent',
64
+ darkSubMenuItemBg: 'transparent',
65
+ darkItemColor: navSurface.text,
66
+ darkItemHoverBg: navSurface.backgroundHover,
67
+ darkItemHoverColor: navSurface.textSelected,
68
+ darkItemSelectedBg: navSurface.backgroundSelected,
69
+ darkItemSelectedColor: navSurface.textSelected,
70
+ darkPopupBg: navSurface.background,
71
+ },
72
+ Table: {
73
+ headerBorderRadius: 0,
74
+ cellPaddingBlock: spacing.sm,
75
+ cellPaddingInline: spacing.md,
76
+ },
77
+ Card: {
78
+ boxShadowTertiary: shadow.card,
79
+ },
80
+ Descriptions: {
81
+ itemPaddingBottom: spacing.sm,
82
+ },
83
+ Form: {
84
+ itemMarginBottom: spacing.md,
85
+ },
86
+ };
87
+ const lightTheme = {
88
+ algorithm: antdTheme.defaultAlgorithm,
89
+ cssVar: {},
90
+ hashed: true,
91
+ token: {
92
+ ...sharedTokens,
93
+ colorBgLayout: neutral[100],
94
+ colorBgContainer: neutral[0],
95
+ colorBgElevated: neutral[0],
96
+ colorBorder: neutral[300],
97
+ colorBorderSecondary: neutral[200],
98
+ colorText: neutral[800],
99
+ colorTextSecondary: neutral[600],
100
+ colorTextTertiary: neutral[500],
101
+ colorTextQuaternary: neutral[400],
102
+ boxShadowSecondary: shadow.popup,
103
+ },
104
+ components: {
105
+ ...sharedComponents,
106
+ Layout: {
107
+ ...sharedComponents?.Layout,
108
+ headerBg: neutral[0],
109
+ bodyBg: neutral[100],
110
+ },
111
+ },
112
+ };
113
+ const darkTheme = {
114
+ algorithm: antdTheme.darkAlgorithm,
115
+ cssVar: {},
116
+ hashed: true,
117
+ token: {
118
+ ...sharedTokens,
119
+ colorBgLayout: neutral[950],
120
+ colorBgContainer: neutral[900],
121
+ colorBgElevated: neutral[800],
122
+ colorBorder: '#2A3538',
123
+ colorBorderSecondary: '#1F292C',
124
+ colorText: '#E4EAEC',
125
+ colorTextSecondary: '#A9B5B9',
126
+ colorTextTertiary: '#7E8C91',
127
+ boxShadowSecondary: '0 6px 16px rgba(0, 0, 0, 0.45)',
128
+ },
129
+ components: {
130
+ ...sharedComponents,
131
+ Layout: {
132
+ ...sharedComponents?.Layout,
133
+ headerBg: neutral[900],
134
+ bodyBg: neutral[950],
135
+ },
136
+ },
137
+ };
138
+ /** The antd theme for a colour mode. The only way to obtain one. */
139
+ export function plantOpsTheme(mode) {
140
+ return mode === 'dark' ? darkTheme : lightTheme;
141
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The PlantOps design language, as raw values (Doc 09 preamble).
3
+ *
4
+ * Doc 09 mandates no component library and leaves visuals to "the project's
5
+ * design language" — this file *is* that design language, written down once so
6
+ * that `admin-web`, and the gatepass and visitor consoles that follow it, are
7
+ * recognisably the same product rather than three applications that happen to
8
+ * share an API.
9
+ *
10
+ * Everything here is a plain value, not an Ant Design concept. {@link theme.ts}
11
+ * translates them into an antd `ThemeConfig`; a chart, an email template or a
12
+ * future non-antd surface can read the same numbers without importing antd.
13
+ *
14
+ * ## The palette, and why it is this one
15
+ *
16
+ * PlantOps administers industrial sites — plants, gates, departments, shift
17
+ * supervisors. Two things follow. First, the interface is used for long
18
+ * stretches on cheap monitors in bright rooms, so the neutrals are cool slates
19
+ * with real contrast rather than the low-contrast greys that photograph well on
20
+ * a designer's laptop. Second, and more importantly: **red, amber and green
21
+ * already mean something on a plant floor**. Reserving them for status is not a
22
+ * stylistic preference here, it is the reason the brand colour is a deep teal.
23
+ * A primary button must never be mistakable for a running/fault indicator.
24
+ */
25
+ /**
26
+ * Brand and status colours.
27
+ *
28
+ * `primary` is the only decorative colour in the set; the other four are
29
+ * semantic and must not be borrowed for emphasis, per the note above.
30
+ */
31
+ export declare const palette: {
32
+ /** Deep teal — brand, primary actions, active navigation. */
33
+ readonly primary: "#0E7C66";
34
+ /** Hover/active step of the primary ramp, used where antd wants a lighter one. */
35
+ readonly primaryHover: "#12977C";
36
+ /** Tint behind selected rows and active menu items. */
37
+ readonly primarySoft: "#E6F4F0";
38
+ /** Informational, never a call to action. */
39
+ readonly info: "#1668DC";
40
+ /** Completed, healthy, active. */
41
+ readonly success: "#2F9E44";
42
+ /** Degraded, expiring, needs attention — locked accounts, expiring bindings. */
43
+ readonly warning: "#D48806";
44
+ /** Failed, denied, revoked. */
45
+ readonly error: "#CF3B33";
46
+ };
47
+ /**
48
+ * Neutrals, coolest to warmest-lightest.
49
+ *
50
+ * The console's dark surfaces (the sidebar, the dark colour mode) come from the
51
+ * `900`–`700` end; page chrome from `100`–`300`.
52
+ */
53
+ export declare const neutral: {
54
+ readonly 0: "#FFFFFF";
55
+ readonly 50: "#F7F9F9";
56
+ readonly 100: "#EFF2F3";
57
+ readonly 200: "#E1E6E8";
58
+ readonly 300: "#CBD3D6";
59
+ readonly 400: "#9AA7AC";
60
+ readonly 500: "#6C7A80";
61
+ readonly 600: "#4C585D";
62
+ readonly 700: "#333D41";
63
+ readonly 800: "#1E2629";
64
+ readonly 900: "#121A1C";
65
+ readonly 950: "#0B1113";
66
+ };
67
+ /**
68
+ * The navigation surface, in both colour modes.
69
+ *
70
+ * Held apart from {@link neutral} because the sidebar is intentionally dark in
71
+ * *both* modes: it is the one region whose appearance should not change when a
72
+ * user flips the theme, so that muscle memory for "where the menu is" survives.
73
+ */
74
+ export declare const navSurface: {
75
+ readonly background: "#121A1C";
76
+ readonly backgroundHover: "#1B2528";
77
+ readonly backgroundSelected: "#14342E";
78
+ readonly text: "#B7C2C6";
79
+ readonly textSelected: "#FFFFFF";
80
+ readonly border: "#1F292C";
81
+ };
82
+ /**
83
+ * Typography.
84
+ *
85
+ * Inter when the host page provides it, then the platform UI stack. The lib
86
+ * deliberately loads no webfont: a shared component library that injects a
87
+ * network request into every consuming app is a decision each app should make
88
+ * for itself.
89
+ */
90
+ export declare const typography: {
91
+ readonly fontFamily: "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif";
92
+ readonly fontFamilyMono: "'JetBrains Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace";
93
+ /** Body size. 14 is antd's default and the right density for admin tables. */
94
+ readonly fontSize: 14;
95
+ readonly fontSizeSm: 12;
96
+ readonly fontSizeLg: 16;
97
+ readonly fontSizeHeading: 20;
98
+ };
99
+ /** A 4px rhythm. Every gap, pad and inset in the library is one of these. */
100
+ export declare const spacing: {
101
+ readonly xxs: 4;
102
+ readonly xs: 8;
103
+ readonly sm: 12;
104
+ readonly md: 16;
105
+ readonly lg: 24;
106
+ readonly xl: 32;
107
+ readonly xxl: 48;
108
+ };
109
+ export declare const radius: {
110
+ readonly sm: 4;
111
+ readonly md: 6;
112
+ readonly lg: 10;
113
+ readonly pill: 999;
114
+ };
115
+ /** Fixed chrome dimensions the shell and its consumers agree on. */
116
+ export declare const layout: {
117
+ readonly headerHeight: 56;
118
+ readonly sidebarWidth: 248;
119
+ readonly sidebarCollapsedWidth: 64;
120
+ /** Maximum width of a reading-oriented page body (forms, detail panels). */
121
+ readonly contentMaxWidth: 1440;
122
+ };
123
+ /** The elevation steps used by cards, dropdowns and drawers. */
124
+ export declare const shadow: {
125
+ readonly card: "0 1px 2px rgba(11, 17, 19, 0.04), 0 1px 3px rgba(11, 17, 19, 0.06)";
126
+ readonly popup: "0 6px 16px rgba(11, 17, 19, 0.12), 0 3px 6px rgba(11, 17, 19, 0.08)";
127
+ };
128
+ /** The two colour modes the theme is defined for. */
129
+ export type ColorMode = 'light' | 'dark';
130
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/theme/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,OAAO;IAClB,6DAA6D;;IAE7D,kFAAkF;;IAElF,uDAAuD;;IAGvD,6CAA6C;;IAE7C,kCAAkC;;IAElC,gFAAgF;;IAEhF,+BAA+B;;CAEvB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;CAaV,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU;;;IAKrB,8EAA8E;;;;;CAKtE,CAAC;AAEX,6EAA6E;AAC7E,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAC;AAEX,eAAO,MAAM,MAAM;;;;;CAKT,CAAC;AAEX,oEAAoE;AACpE,eAAO,MAAM,MAAM;;;;IAIjB,4EAA4E;;CAEpE,CAAC;AAEX,gEAAgE;AAChE,eAAO,MAAM,MAAM;;;CAGT,CAAC;AAEX,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The PlantOps design language, as raw values (Doc 09 preamble).
3
+ *
4
+ * Doc 09 mandates no component library and leaves visuals to "the project's
5
+ * design language" — this file *is* that design language, written down once so
6
+ * that `admin-web`, and the gatepass and visitor consoles that follow it, are
7
+ * recognisably the same product rather than three applications that happen to
8
+ * share an API.
9
+ *
10
+ * Everything here is a plain value, not an Ant Design concept. {@link theme.ts}
11
+ * translates them into an antd `ThemeConfig`; a chart, an email template or a
12
+ * future non-antd surface can read the same numbers without importing antd.
13
+ *
14
+ * ## The palette, and why it is this one
15
+ *
16
+ * PlantOps administers industrial sites — plants, gates, departments, shift
17
+ * supervisors. Two things follow. First, the interface is used for long
18
+ * stretches on cheap monitors in bright rooms, so the neutrals are cool slates
19
+ * with real contrast rather than the low-contrast greys that photograph well on
20
+ * a designer's laptop. Second, and more importantly: **red, amber and green
21
+ * already mean something on a plant floor**. Reserving them for status is not a
22
+ * stylistic preference here, it is the reason the brand colour is a deep teal.
23
+ * A primary button must never be mistakable for a running/fault indicator.
24
+ */
25
+ /**
26
+ * Brand and status colours.
27
+ *
28
+ * `primary` is the only decorative colour in the set; the other four are
29
+ * semantic and must not be borrowed for emphasis, per the note above.
30
+ */
31
+ export const palette = {
32
+ /** Deep teal — brand, primary actions, active navigation. */
33
+ primary: '#0E7C66',
34
+ /** Hover/active step of the primary ramp, used where antd wants a lighter one. */
35
+ primaryHover: '#12977C',
36
+ /** Tint behind selected rows and active menu items. */
37
+ primarySoft: '#E6F4F0',
38
+ /** Informational, never a call to action. */
39
+ info: '#1668DC',
40
+ /** Completed, healthy, active. */
41
+ success: '#2F9E44',
42
+ /** Degraded, expiring, needs attention — locked accounts, expiring bindings. */
43
+ warning: '#D48806',
44
+ /** Failed, denied, revoked. */
45
+ error: '#CF3B33',
46
+ };
47
+ /**
48
+ * Neutrals, coolest to warmest-lightest.
49
+ *
50
+ * The console's dark surfaces (the sidebar, the dark colour mode) come from the
51
+ * `900`–`700` end; page chrome from `100`–`300`.
52
+ */
53
+ export const neutral = {
54
+ 0: '#FFFFFF',
55
+ 50: '#F7F9F9',
56
+ 100: '#EFF2F3',
57
+ 200: '#E1E6E8',
58
+ 300: '#CBD3D6',
59
+ 400: '#9AA7AC',
60
+ 500: '#6C7A80',
61
+ 600: '#4C585D',
62
+ 700: '#333D41',
63
+ 800: '#1E2629',
64
+ 900: '#121A1C',
65
+ 950: '#0B1113',
66
+ };
67
+ /**
68
+ * The navigation surface, in both colour modes.
69
+ *
70
+ * Held apart from {@link neutral} because the sidebar is intentionally dark in
71
+ * *both* modes: it is the one region whose appearance should not change when a
72
+ * user flips the theme, so that muscle memory for "where the menu is" survives.
73
+ */
74
+ export const navSurface = {
75
+ background: neutral[900],
76
+ backgroundHover: '#1B2528',
77
+ backgroundSelected: '#14342E',
78
+ text: '#B7C2C6',
79
+ textSelected: '#FFFFFF',
80
+ border: '#1F292C',
81
+ };
82
+ /**
83
+ * Typography.
84
+ *
85
+ * Inter when the host page provides it, then the platform UI stack. The lib
86
+ * deliberately loads no webfont: a shared component library that injects a
87
+ * network request into every consuming app is a decision each app should make
88
+ * for itself.
89
+ */
90
+ export const typography = {
91
+ fontFamily: "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
92
+ fontFamilyMono: "'JetBrains Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace",
93
+ /** Body size. 14 is antd's default and the right density for admin tables. */
94
+ fontSize: 14,
95
+ fontSizeSm: 12,
96
+ fontSizeLg: 16,
97
+ fontSizeHeading: 20,
98
+ };
99
+ /** A 4px rhythm. Every gap, pad and inset in the library is one of these. */
100
+ export const spacing = {
101
+ xxs: 4,
102
+ xs: 8,
103
+ sm: 12,
104
+ md: 16,
105
+ lg: 24,
106
+ xl: 32,
107
+ xxl: 48,
108
+ };
109
+ export const radius = {
110
+ sm: 4,
111
+ md: 6,
112
+ lg: 10,
113
+ pill: 999,
114
+ };
115
+ /** Fixed chrome dimensions the shell and its consumers agree on. */
116
+ export const layout = {
117
+ headerHeight: 56,
118
+ sidebarWidth: 248,
119
+ sidebarCollapsedWidth: 64,
120
+ /** Maximum width of a reading-oriented page body (forms, detail panels). */
121
+ contentMaxWidth: 1440,
122
+ };
123
+ /** The elevation steps used by cards, dropdowns and drawers. */
124
+ export const shadow = {
125
+ card: '0 1px 2px rgba(11, 17, 19, 0.04), 0 1px 3px rgba(11, 17, 19, 0.06)',
126
+ popup: '0 6px 16px rgba(11, 17, 19, 0.12), 0 3px 6px rgba(11, 17, 19, 0.08)',
127
+ };