@olenbetong/appframe-ds 0.4.1 → 0.6.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 (128) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/package.json +4 -4
  3. package/scripts/copyAssets.mjs +12 -0
  4. package/src/AfLookup/Lookup.tsx +3 -4
  5. package/src/AfLookup/LookupEdit.tsx +3 -4
  6. package/src/binding/CancelButton.tsx +4 -1
  7. package/src/binding/CancelIconButton.tsx +2 -2
  8. package/src/binding/DataEditToolbar.tsx +1 -2
  9. package/src/binding/DeleteButton.tsx +6 -2
  10. package/src/binding/DeleteIconButton.tsx +5 -4
  11. package/src/binding/RefreshButton.tsx +7 -3
  12. package/src/binding/RefreshIconButton.tsx +6 -5
  13. package/src/binding/RefreshRowIconButton.tsx +6 -5
  14. package/src/binding/SaveButton.tsx +14 -4
  15. package/src/binding/SaveIconButton.tsx +13 -6
  16. package/src/index.ts +5 -0
  17. package/src/input/InputAdornments.css +75 -0
  18. package/src/input/InputAdornments.tsx +97 -0
  19. package/src/input/index.ts +1 -0
  20. package/src/layout/AppLayoutDesktop.tsx +3 -0
  21. package/src/layout/AppLayoutMobile.tsx +3 -0
  22. package/src/layout/AppMenu.css +1 -0
  23. package/src/layout/PageContainer.tsx +6 -0
  24. package/src/layout/index.tsx +5 -0
  25. package/src/list/ItemList.css +30 -0
  26. package/src/list/ItemList.tsx +52 -0
  27. package/src/list/ItemListItem.tsx +41 -0
  28. package/src/list/ItemListItemText.tsx +23 -0
  29. package/src/list/index.ts +3 -0
  30. package/src/page/Page.css +45 -0
  31. package/src/page/Page.tsx +70 -0
  32. package/src/page/PageBlock.css +59 -0
  33. package/src/page/PageBlock.tsx +78 -0
  34. package/src/page/PageHeader.css +148 -0
  35. package/src/page/PageHeader.tsx +184 -0
  36. package/src/page/index.ts +3 -0
  37. package/src/paper/Paper.css +35 -0
  38. package/src/paper/Paper.tsx +50 -0
  39. package/src/paper/index.ts +1 -0
  40. package/src/progress/LinearProgress.css +93 -0
  41. package/src/progress/LinearProgress.tsx +104 -0
  42. package/src/progress/index.ts +1 -0
  43. package/es/AfLookup/BoundLookup.d.ts +0 -10
  44. package/es/AfLookup/BoundLookup.js +0 -16
  45. package/es/AfLookup/Combobox.css +0 -78
  46. package/es/AfLookup/Combobox.d.ts +0 -32
  47. package/es/AfLookup/Combobox.js +0 -76
  48. package/es/AfLookup/Lookup.css +0 -125
  49. package/es/AfLookup/Lookup.d.ts +0 -35
  50. package/es/AfLookup/Lookup.js +0 -59
  51. package/es/AfLookup/LookupEdit.d.ts +0 -21
  52. package/es/AfLookup/LookupEdit.js +0 -49
  53. package/es/AfLookup/LookupGrid.css +0 -57
  54. package/es/AfLookup/LookupGrid.d.ts +0 -13
  55. package/es/AfLookup/LookupGrid.js +0 -27
  56. package/es/AfLookup/index.d.ts +0 -5
  57. package/es/AfLookup/index.js +0 -5
  58. package/es/binding/BoundCheckbox.d.ts +0 -9
  59. package/es/binding/BoundCheckbox.js +0 -13
  60. package/es/binding/BoundDatePicker.d.ts +0 -7
  61. package/es/binding/BoundDatePicker.js +0 -12
  62. package/es/binding/BoundDateTimePicker.d.ts +0 -7
  63. package/es/binding/BoundDateTimePicker.js +0 -14
  64. package/es/binding/BoundInput.d.ts +0 -6
  65. package/es/binding/BoundInput.js +0 -12
  66. package/es/binding/BoundNumericTextField.d.ts +0 -20
  67. package/es/binding/BoundNumericTextField.js +0 -58
  68. package/es/binding/BoundSelect.d.ts +0 -9
  69. package/es/binding/BoundSelect.js +0 -13
  70. package/es/binding/BoundSwitch.d.ts +0 -9
  71. package/es/binding/BoundSwitch.js +0 -13
  72. package/es/binding/BoundTextField.d.ts +0 -7
  73. package/es/binding/BoundTextField.js +0 -22
  74. package/es/binding/CancelButton.d.ts +0 -3
  75. package/es/binding/CancelButton.js +0 -14
  76. package/es/binding/CancelIconButton.d.ts +0 -2
  77. package/es/binding/CancelIconButton.js +0 -15
  78. package/es/binding/DataEditToolbar.d.ts +0 -13
  79. package/es/binding/DataEditToolbar.js +0 -28
  80. package/es/binding/DataObjectSelect.d.ts +0 -50
  81. package/es/binding/DataObjectSelect.js +0 -26
  82. package/es/binding/DeleteButton.d.ts +0 -8
  83. package/es/binding/DeleteButton.js +0 -14
  84. package/es/binding/DeleteIconButton.d.ts +0 -10
  85. package/es/binding/DeleteIconButton.js +0 -15
  86. package/es/binding/RefreshButton.d.ts +0 -3
  87. package/es/binding/RefreshButton.js +0 -14
  88. package/es/binding/RefreshIconButton.d.ts +0 -2
  89. package/es/binding/RefreshIconButton.js +0 -16
  90. package/es/binding/RefreshRowIconButton.d.ts +0 -7
  91. package/es/binding/RefreshRowIconButton.js +0 -15
  92. package/es/binding/SaveButton.d.ts +0 -3
  93. package/es/binding/SaveButton.js +0 -14
  94. package/es/binding/SaveIconButton.d.ts +0 -2
  95. package/es/binding/SaveIconButton.js +0 -15
  96. package/es/binding/index.d.ts +0 -19
  97. package/es/binding/index.js +0 -19
  98. package/es/index.d.ts +0 -3
  99. package/es/index.js +0 -3
  100. package/es/layout/AppLayoutDesktop.css +0 -65
  101. package/es/layout/AppLayoutDesktop.d.ts +0 -3
  102. package/es/layout/AppLayoutDesktop.js +0 -19
  103. package/es/layout/AppLayoutMobile.css +0 -75
  104. package/es/layout/AppLayoutMobile.d.ts +0 -3
  105. package/es/layout/AppLayoutMobile.js +0 -18
  106. package/es/layout/AppMenu.css +0 -67
  107. package/es/layout/AppMenu.d.ts +0 -8
  108. package/es/layout/AppMenu.js +0 -36
  109. package/es/layout/AppMenuItem.css +0 -97
  110. package/es/layout/AppMenuItem.d.ts +0 -50
  111. package/es/layout/AppMenuItem.js +0 -14
  112. package/es/layout/AppMenuSubheader.css +0 -18
  113. package/es/layout/AppMenuSubheader.d.ts +0 -4
  114. package/es/layout/AppMenuSubheader.js +0 -6
  115. package/es/layout/ErrorBoundary.css +0 -101
  116. package/es/layout/ErrorBoundary.d.ts +0 -30
  117. package/es/layout/ErrorBoundary.js +0 -81
  118. package/es/layout/PageContainer.css +0 -29
  119. package/es/layout/PageContainer.d.ts +0 -7
  120. package/es/layout/PageContainer.js +0 -6
  121. package/es/layout/PartnerToggle.d.ts +0 -5
  122. package/es/layout/PartnerToggle.js +0 -9
  123. package/es/layout/constants.d.ts +0 -2
  124. package/es/layout/constants.js +0 -2
  125. package/es/layout/index.css +0 -65
  126. package/es/layout/index.d.ts +0 -33
  127. package/es/layout/index.js +0 -31
  128. package/tsconfig.build.tsbuildinfo +0 -1
@@ -0,0 +1,184 @@
1
+ import "./PageHeader.css";
2
+
3
+ import { getLocalizedString } from "@olenbetong/appframe-core";
4
+
5
+ import clsx from "clsx";
6
+ import type React from "react";
7
+ import { useEffect, useRef, useState } from "react";
8
+ import { useLocation } from "react-router";
9
+
10
+ import { AppMenu, type AppMenuProps } from "../layout/AppMenu.js";
11
+ import { PageBlock, type PageBlockWidth } from "./PageBlock.js";
12
+
13
+ export type PageHeaderVariant = "appbar" | "plain";
14
+
15
+ export type PageHeaderProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
16
+ /**
17
+ * Actions displayed at the end of the header (buttons, search, etc.)
18
+ */
19
+ actions?: React.ReactNode;
20
+ /**
21
+ * Props passed to the `AppMenu` wrapping the `menu` content
22
+ */
23
+ AppMenuProps?: AppMenuProps;
24
+ children?: React.ReactNode;
25
+ /**
26
+ * App menu (navigation) content. When provided, the `appbar` variant
27
+ * renders a menu toggle button and a drawer hosting the menu — docked on
28
+ * desktop (≥1200px), overlay on smaller screens.
29
+ */
30
+ menu?: React.ReactNode;
31
+ /**
32
+ * Application title
33
+ */
34
+ title?: React.ReactNode;
35
+ /**
36
+ * Adds a standardised responsive inline padding to the header content.
37
+ * See `Page.Block`.
38
+ * @default false
39
+ */
40
+ gutters?: boolean;
41
+ /**
42
+ * Constrains and centers the header content to a predefined max-width,
43
+ * so it can align with a `Page.Block` of the same width. See `Page.Block`.
44
+ */
45
+ width?: PageBlockWidth;
46
+ /**
47
+ * - `"appbar"` (default): a top app bar with menu toggle, title and
48
+ * actions. For apps that have an app menu.
49
+ * - `"plain"`: no app bar chrome — for simple apps without an app menu
50
+ * (e.g. report-issue). Renders the title as a regular heading block.
51
+ *
52
+ * Both variants reserve an end-slot (`.ObPageHeader-end`) that will host
53
+ * the app-launcher and user profile menu in the future sidebar-free site
54
+ * layout. It is hidden under the current sidebar layout.
55
+ * @default "appbar"
56
+ */
57
+ variant?: PageHeaderVariant;
58
+ };
59
+
60
+ function useIsMobile() {
61
+ let [isMobile, setIsMobile] = useState(() => {
62
+ if (typeof window === "undefined") return false;
63
+ return window.matchMedia("(max-width: 1199px)").matches;
64
+ });
65
+
66
+ useEffect(() => {
67
+ let mq = window.matchMedia("(max-width: 1199px)");
68
+ let handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);
69
+ mq.addEventListener("change", handler);
70
+ return () => mq.removeEventListener("change", handler);
71
+ }, []);
72
+
73
+ return isMobile;
74
+ }
75
+
76
+ type PageHeaderDrawerProps = {
77
+ AppMenuProps?: AppMenuProps;
78
+ menu: React.ReactNode;
79
+ onClose: () => void;
80
+ isMobile: boolean;
81
+ open: boolean;
82
+ };
83
+
84
+ function PageHeaderDrawer({ AppMenuProps, menu, onClose, isMobile, open }: PageHeaderDrawerProps) {
85
+ let location = useLocation();
86
+ let prevLocation = useRef(location);
87
+
88
+ useEffect(() => {
89
+ if (location !== prevLocation.current) {
90
+ prevLocation.current = location;
91
+ if (isMobile) onClose();
92
+ }
93
+ }, [location, isMobile, onClose]);
94
+
95
+ return (
96
+ <>
97
+ {isMobile && (
98
+ <div
99
+ className={clsx("ObPageHeader-drawerOverlay", open && "ObPageHeader-drawerOpen")}
100
+ onClick={onClose}
101
+ aria-hidden="true"
102
+ />
103
+ )}
104
+ <div
105
+ className={clsx(
106
+ "ObPageHeader-drawer",
107
+ "AppMenu-drawer",
108
+ isMobile ? "ObPageHeader-drawerOverlayMode" : "ObPageHeader-drawerDocked",
109
+ open && "ObPageHeader-drawerOpen",
110
+ )}
111
+ >
112
+ <AppMenu {...AppMenuProps}>{menu}</AppMenu>
113
+ </div>
114
+ </>
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Page header for use inside `Page`. See the `variant` prop for the two
120
+ * supported header styles.
121
+ */
122
+ export function PageHeader({
123
+ actions,
124
+ AppMenuProps,
125
+ children,
126
+ className,
127
+ gutters,
128
+ menu,
129
+ title,
130
+ variant = "appbar",
131
+ width,
132
+ ...props
133
+ }: PageHeaderProps) {
134
+ let isMobile = useIsMobile();
135
+ let [desktopOpen, setDesktopOpen] = useState(true);
136
+ let [mobileOpen, setMobileOpen] = useState(false);
137
+
138
+ let open = isMobile ? mobileOpen : desktopOpen;
139
+ let toggle = () => (isMobile ? setMobileOpen((o) => !o) : setDesktopOpen((o) => !o));
140
+
141
+ if (variant === "plain") {
142
+ return (
143
+ <header className={clsx("ObPageHeader-root", "ObPageHeader-plain", className)} {...props}>
144
+ <PageBlock className="ObPageHeader-plainInner" width={width} gutters={gutters}>
145
+ {title && <h1 className="ObPageHeader-plainTitle">{title}</h1>}
146
+ {actions && <div className="ObPageHeader-actions">{actions}</div>}
147
+ {children}
148
+ <div className="ObPageHeader-end" />
149
+ </PageBlock>
150
+ </header>
151
+ );
152
+ }
153
+
154
+ return (
155
+ <header className={clsx("ObPageHeader-root", "ObPageHeader-appbar", className)} {...props}>
156
+ <PageBlock className="ObPageHeader-bar" width={width} gutters={gutters}>
157
+ {menu && (
158
+ <button
159
+ type="button"
160
+ className="ObPageHeader-toggle"
161
+ onClick={toggle}
162
+ aria-label={getLocalizedString("Toggle menu")}
163
+ aria-expanded={open}
164
+ >
165
+ ☰
166
+ </button>
167
+ )}
168
+ {title && <h1 className="ObPageHeader-title">{title}</h1>}
169
+ {actions && <div className="ObPageHeader-actions">{actions}</div>}
170
+ <div className="ObPageHeader-end" />
171
+ </PageBlock>
172
+ {children}
173
+ {menu && (
174
+ <PageHeaderDrawer
175
+ AppMenuProps={AppMenuProps}
176
+ menu={menu}
177
+ onClose={() => setMobileOpen(false)}
178
+ isMobile={isMobile}
179
+ open={open}
180
+ />
181
+ )}
182
+ </header>
183
+ );
184
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./Page.js";
2
+ export * from "./PageBlock.js";
3
+ export * from "./PageHeader.js";
@@ -0,0 +1,35 @@
1
+ .ObPaper-root {
2
+ background-color: var(--ds-color-neutral-surface-default, #fff);
3
+ color: var(--ds-color-neutral-text-default, #1e2b3c);
4
+ border-radius: var(--ds-border-radius-md, 0.375rem);
5
+ }
6
+
7
+ .ObPaper-shadow-xs {
8
+ box-shadow: var(--ds-shadow-xs);
9
+ }
10
+
11
+ .ObPaper-shadow-sm {
12
+ box-shadow: var(--ds-shadow-sm);
13
+ }
14
+
15
+ .ObPaper-shadow-md {
16
+ box-shadow: var(--ds-shadow-md);
17
+ }
18
+
19
+ .ObPaper-shadow-lg {
20
+ box-shadow: var(--ds-shadow-lg);
21
+ }
22
+
23
+ .ObPaper-shadow-xl {
24
+ box-shadow: var(--ds-shadow-xl);
25
+ }
26
+
27
+ .ObPaper-border {
28
+ border: var(--ds-border-width-default, 1px) solid var(--ds-color-neutral-border-subtle, #dfdfdf);
29
+ }
30
+
31
+ @media print {
32
+ .ObPaper-root {
33
+ box-shadow: none;
34
+ }
35
+ }
@@ -0,0 +1,50 @@
1
+ import "./Paper.css";
2
+
3
+ import clsx from "clsx";
4
+ import type React from "react";
5
+
6
+ export const paperShadows = ["none", "xs", "sm", "md", "lg", "xl"] as const;
7
+
8
+ export type PaperShadow = (typeof paperShadows)[number];
9
+
10
+ export type PaperProps = React.HTMLAttributes<HTMLElement> & {
11
+ /**
12
+ * Overrides the rendered element (e.g. `"section"`, `"ul"`)
13
+ * @default "div"
14
+ */
15
+ as?: React.ElementType;
16
+ /**
17
+ * Adds a subtle border. Combine with `shadow="none"` for an outlined
18
+ * variant (MUI `variant="outlined"` equivalent).
19
+ * @default false
20
+ */
21
+ border?: boolean;
22
+ children?: React.ReactNode;
23
+ /**
24
+ * Elevation shadow, using the designsystemet `--ds-shadow-*` tokens.
25
+ * @default "sm"
26
+ */
27
+ shadow?: PaperShadow;
28
+ };
29
+
30
+ /**
31
+ * Surface component equivalent to MUI `Paper`: a neutral surface with
32
+ * rounded corners and an elevation shadow. Use it instead of hand-rolled
33
+ * `background` + `box-shadow` CSS so surfaces stay consistent with the
34
+ * designsystemet tokens (and adapt to dark mode).
35
+ */
36
+ export function Paper({ as: Component = "div", border, children, className, shadow = "sm", ...props }: PaperProps) {
37
+ return (
38
+ <Component
39
+ className={clsx(
40
+ "ObPaper-root",
41
+ shadow !== "none" && `ObPaper-shadow-${shadow}`,
42
+ border && "ObPaper-border",
43
+ className,
44
+ )}
45
+ {...props}
46
+ >
47
+ {children}
48
+ </Component>
49
+ );
50
+ }
@@ -0,0 +1 @@
1
+ export * from "./Paper.js";
@@ -0,0 +1,93 @@
1
+ .ObLinearProgress-root {
2
+ --obLinearProgress-thickness: 0.25rem;
3
+ --obLinearProgress-duration: 2.1s;
4
+
5
+ position: relative;
6
+ display: block;
7
+ box-sizing: border-box;
8
+ inline-size: 100%;
9
+ block-size: var(--obLinearProgress-thickness);
10
+ overflow: hidden;
11
+ background-color: var(--ds-color-surface-active, #cddffb);
12
+ border-radius: var(--ds-border-radius-full, 624.9375rem);
13
+ }
14
+
15
+ .ObLinearProgress-root[data-size="xs"] {
16
+ --obLinearProgress-thickness: 0.125rem;
17
+ }
18
+
19
+ .ObLinearProgress-root[data-size="sm"] {
20
+ --obLinearProgress-thickness: 0.25rem;
21
+ }
22
+
23
+ .ObLinearProgress-root[data-size="md"] {
24
+ --obLinearProgress-thickness: 0.5rem;
25
+ }
26
+
27
+ .ObLinearProgress-root[data-size="lg"] {
28
+ --obLinearProgress-thickness: 0.75rem;
29
+ }
30
+
31
+ .ObLinearProgress-bar {
32
+ position: absolute;
33
+ inset-block: 0;
34
+ inset-inline-start: 0;
35
+ inline-size: 100%;
36
+ background-color: var(--ds-color-base-default, #0062ba);
37
+ border-radius: inherit;
38
+ }
39
+
40
+ .ObLinearProgress-determinate .ObLinearProgress-bar {
41
+ transition: inline-size 0.2s linear;
42
+ }
43
+
44
+ /*
45
+ * The indeterminate bar is full width and animated with `transform`, where the
46
+ * start and end of the bar move at different speeds (the bar stretches and
47
+ * shrinks as it travels).
48
+ */
49
+ .ObLinearProgress-indeterminate .ObLinearProgress-bar {
50
+ transform-origin: left center;
51
+ will-change: transform;
52
+ animation: ObLinearProgress-indeterminate var(--obLinearProgress-duration) cubic-bezier(0.65, 0.815, 0.735, 0.395)
53
+ infinite;
54
+ }
55
+
56
+ /* Zero-height wrapper so the overlay bar never affects the layout */
57
+ .ObLinearProgress-overlay {
58
+ position: relative;
59
+ z-index: 1;
60
+ block-size: 0;
61
+ }
62
+
63
+ .ObLinearProgress-overlay > .ObLinearProgress-root {
64
+ position: absolute;
65
+ inset-block-start: 0;
66
+ inset-inline: 0;
67
+ }
68
+
69
+ @keyframes ObLinearProgress-indeterminate {
70
+ 0% {
71
+ transform: translateX(-35%) scaleX(0.35);
72
+ }
73
+
74
+ 60% {
75
+ transform: translateX(60%) scaleX(0.7);
76
+ }
77
+
78
+ 100% {
79
+ transform: translateX(100%) scaleX(0.2);
80
+ }
81
+ }
82
+
83
+ @media (prefers-reduced-motion: reduce) {
84
+ .ObLinearProgress-indeterminate .ObLinearProgress-bar {
85
+ animation-duration: 4s;
86
+ }
87
+ }
88
+
89
+ @media print {
90
+ .ObLinearProgress-root {
91
+ display: none;
92
+ }
93
+ }
@@ -0,0 +1,104 @@
1
+ import "./LinearProgress.css";
2
+
3
+ import clsx from "clsx";
4
+ import type React from "react";
5
+
6
+ export const linearProgressSizes = ["xs", "sm", "md", "lg"] as const;
7
+
8
+ export type LinearProgressSize = (typeof linearProgressSizes)[number];
9
+
10
+ export type LinearProgressProps = Omit<React.HTMLAttributes<HTMLDivElement>, "color"> & {
11
+ /**
12
+ * Designsystemet colour palette used for the bar
13
+ * @default "accent"
14
+ */
15
+ "data-color"?: string;
16
+ /**
17
+ * Thickness of the bar
18
+ * @default "sm"
19
+ */
20
+ "data-size"?: LinearProgressSize;
21
+ /**
22
+ * Renders the bar absolutely positioned in a zero-height wrapper, so it
23
+ * overlays the top of the following content instead of taking up space.
24
+ * Use it for loading indicators that should not shift the layout.
25
+ * @default false
26
+ */
27
+ overlay?: boolean;
28
+ /**
29
+ * Progress value. When omitted the bar is indeterminate.
30
+ */
31
+ value?: number;
32
+ /**
33
+ * Highest possible value of `value`
34
+ * @default 100
35
+ */
36
+ valueMax?: number;
37
+ /**
38
+ * Lowest possible value of `value`
39
+ * @default 0
40
+ */
41
+ valueMin?: number;
42
+ };
43
+
44
+ /**
45
+ * Linear progress indicator, equivalent to MUI `LinearProgress`. Indeterminate
46
+ * by default, determinate when `value` is given. Designsystemet has no linear
47
+ * progress component, so this is built with the designsystemet colour and
48
+ * radius tokens (use `data-color` to change palette).
49
+ *
50
+ * @example
51
+ * ```jsx
52
+ * // Indeterminate, in the normal document flow
53
+ * <LinearProgress aria-label="Loading..." />
54
+ *
55
+ * // Determinate
56
+ * <LinearProgress aria-label="Uploading" value={40} />
57
+ *
58
+ * // Absolutely positioned, does not affect the layout
59
+ * <LinearProgress overlay aria-label="Loading..." />
60
+ * ```
61
+ */
62
+ export function LinearProgress({
63
+ className,
64
+ overlay,
65
+ value,
66
+ valueMax = 100,
67
+ valueMin = 0,
68
+ "data-color": color = "accent",
69
+ "data-size": size = "sm",
70
+ ...props
71
+ }: LinearProgressProps) {
72
+ let isDeterminate = typeof value === "number" && Number.isFinite(value);
73
+ let clamped = isDeterminate ? Math.min(Math.max(value as number, valueMin), valueMax) : undefined;
74
+ let percentage =
75
+ clamped === undefined || valueMax === valueMin ? undefined : ((clamped - valueMin) / (valueMax - valueMin)) * 100;
76
+
77
+ let bar = (
78
+ <div
79
+ className={clsx(
80
+ "ObLinearProgress-root",
81
+ isDeterminate ? "ObLinearProgress-determinate" : "ObLinearProgress-indeterminate",
82
+ !overlay && className,
83
+ )}
84
+ data-color={color}
85
+ data-size={size}
86
+ role="progressbar"
87
+ aria-valuemin={valueMin}
88
+ aria-valuemax={valueMax}
89
+ aria-valuenow={clamped}
90
+ {...props}
91
+ >
92
+ <div
93
+ className="ObLinearProgress-bar"
94
+ style={percentage === undefined ? undefined : { inlineSize: `${percentage}%` }}
95
+ />
96
+ </div>
97
+ );
98
+
99
+ if (!overlay) {
100
+ return bar;
101
+ }
102
+
103
+ return <div className={clsx("ObLinearProgress-overlay", className)}>{bar}</div>;
104
+ }
@@ -0,0 +1 @@
1
+ export * from "./LinearProgress.js";
@@ -1,10 +0,0 @@
1
- import type { CurrentRow, DataObject } from "@olenbetong/appframe-data";
2
- import { type DistributiveOmit } from "@olenbetong/appframe-react";
3
- import { type AfLookupProps } from "./Lookup.js";
4
- export type BoundLookupProps<TBoundData extends Record<string, unknown>, TLookupData extends Record<string, unknown>> = DistributiveOmit<AfLookupProps<TLookupData>, "onChange"> & {
5
- dataObject: DataObject<TLookupData>;
6
- displayField?: keyof TBoundData;
7
- getChanges: (selectedItem: TLookupData | null) => Partial<TBoundData>;
8
- getDisplayValue?: (currentRow: CurrentRow<TBoundData>) => string;
9
- };
10
- export declare function BoundLookup<TBoundData extends Record<string, unknown>, TLookupData extends Record<string, unknown> = any>({ dataObject, displayField, getChanges, getDisplayValue, ...props }: BoundLookupProps<TBoundData, TLookupData>): import("react").JSX.Element;
@@ -1,16 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useCurrentRow, useDataObject } from "@olenbetong/appframe-react";
3
- import { AfLookup } from "./Lookup.js";
4
- export function BoundLookup({ dataObject, displayField, getChanges, getDisplayValue, ...props }) {
5
- let boundDataObject = useDataObject();
6
- let row = useCurrentRow(boundDataObject);
7
- function handleChange(item) {
8
- let changes = getChanges(item);
9
- for (let key in changes) {
10
- let newValue = changes[key];
11
- boundDataObject.currentRow(key, newValue);
12
- }
13
- }
14
- let displayValue = getDisplayValue ? getDisplayValue(row) : displayField ? String(row[displayField] ?? "") : "";
15
- return _jsx(AfLookup, { dataObject: dataObject, value: displayValue, onChange: handleChange, ...props });
16
- }
@@ -1,78 +0,0 @@
1
- .ObCombobox-root {
2
- height: 100%;
3
- display: grid;
4
- grid-template-rows: min-content auto 1fr;
5
- gap: 0.5rem;
6
-
7
- overscroll-behavior: contain;
8
- }
9
-
10
- .ObCombobox-actions {
11
- display: flex;
12
- justify-content: space-between;
13
- }
14
-
15
- .ObCombobox-listWrap {
16
- overflow: hidden;
17
- min-height: 0;
18
- border: 1px solid rgb(0 0 0 / 0.12);
19
- border-radius: 0.25rem;
20
- background-color: white;
21
- }
22
-
23
- .ObCombobox-list {
24
- border: 1px solid rgb(0 0 0 / 0.06);
25
- height: 100%;
26
- overflow-y: hidden;
27
- overscroll-behavior: contain;
28
- list-style: none;
29
- margin: 0;
30
- padding: 0;
31
- }
32
-
33
- .ObCombobox-input {
34
- background-color: white;
35
- }
36
-
37
- .ObCombobox-listItem {
38
- --active-color: oklch(from var(--brand-secondary, #999) l c h / 50%);
39
- cursor: pointer;
40
-
41
- &.active {
42
- background-color: var(--active-color);
43
- }
44
-
45
- &:hover {
46
- background-color: rgb(0 0 0 / 0.06);
47
- }
48
-
49
- &.active:hover {
50
- background-color: oklch(from var(--active-color) calc(l + 0.1) calc(c - 0.04) h);
51
- }
52
- }
53
-
54
- .ObCombobox-progress {
55
- position: relative;
56
- height: 4px;
57
- overflow: hidden;
58
- background-color: rgb(0 0 0 / 0.08);
59
- }
60
-
61
- .ObCombobox-progress-bar {
62
- position: absolute;
63
- top: 0;
64
- left: -100%;
65
- height: 100%;
66
- width: 50%;
67
- background-color: var(--ds-color-accent-base-default, #0062ba);
68
- animation: ObCombobox-progress-anim 1.5s ease-in-out infinite;
69
- }
70
-
71
- @keyframes ObCombobox-progress-anim {
72
- 0% {
73
- left: -100%;
74
- }
75
- 100% {
76
- left: 200%;
77
- }
78
- }
@@ -1,32 +0,0 @@
1
- import "./Combobox.css";
2
- import type { DataObject } from "@olenbetong/appframe-data";
3
- import { type LookupColumn } from "@olenbetong/appframe-react";
4
- export interface ComboboxBaseProps<T extends Record<string, unknown>> {
5
- nullable?: boolean;
6
- dataObject: DataObject<T>;
7
- uniqueIdField?: string;
8
- initialSearchValue?: string;
9
- isItemSelected?: (item: T) => boolean;
10
- onChange?: (item: T | null) => void;
11
- value?: T;
12
- onClose?: () => void;
13
- }
14
- export interface ComboboxListProps<T extends Record<string, unknown>> extends ComboboxBaseProps<T> {
15
- /**
16
- * Renders the popup content as a list (default).
17
- */
18
- variant?: "list";
19
- renderItem: (props: React.ComponentPropsWithRef<"li"> & {
20
- item: T;
21
- }) => React.ReactNode;
22
- }
23
- export interface ComboboxGridProps<T extends Record<string, unknown>> extends ComboboxBaseProps<T> {
24
- /**
25
- * Renders the popup content as a grid with a header row and one column per
26
- * entry in `columns`.
27
- */
28
- variant: "grid";
29
- columns: LookupColumn<T>[];
30
- }
31
- export type ComboboxProps<T extends Record<string, unknown>> = ComboboxListProps<T> | ComboboxGridProps<T>;
32
- export declare function Combobox<T extends Record<string, unknown>>(props: ComboboxProps<T>): import("react").JSX.Element;