@olenbetong/synergi-react 2.0.1 → 2.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olenbetong/synergi-react",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "Standalone React component for SynergiWeb and Partner Portal",
5
5
  "type": "module",
6
6
  "types": "./es/index.d.ts",
@@ -79,8 +79,7 @@
79
79
  "replace-in-files": "^3.0.0"
80
80
  },
81
81
  "scripts": {
82
- "build": "pnpm run build:tsc && pnpm run build:tsc:post && pnpm run build:esbuild && pnpm run build:sass && pnpm run build:sass:components",
83
- "build:tsc": "find . -name '*.tsbuildinfo' -delete && rm -rf ./es && tsc",
82
+ "build": "pnpm run build:tsc:post && pnpm run build:esbuild && pnpm run build:sass && pnpm run build:sass:components",
84
83
  "build:esbuild": "rm -rf ./dist && node --experimental-strip-types ../../scripts/esbuild.ts",
85
84
  "build:sass": "sass ./src/index.scss ./dist/styles/styles.css --source-map-urls=relative --style compressed",
86
85
  "build:sass:components": "node ./scripts/buildSassComponents.mjs",
@@ -0,0 +1,96 @@
1
+ :root {
2
+ --ob-datenavigator-height: 3rem;
3
+ }
4
+
5
+ .ObDateNavigator-icon {
6
+ display: inline-block;
7
+
8
+ svg {
9
+ width: 0.625em;
10
+ position: relative;
11
+ top: -1px;
12
+ }
13
+ }
14
+
15
+ .ObDateNavigator-root {
16
+ background-color: hsl(220, 20%, 96%);
17
+ background-color: var(--block-header-color-bg);
18
+ display: flex;
19
+ font-size: 1rem;
20
+ outline: none;
21
+
22
+ &:focus-visible {
23
+ outline: 2px solid var(--brand-dark, #336699);
24
+ outline-offset: 2px;
25
+ }
26
+ }
27
+
28
+ .ObDateNavigator-arrow {
29
+ display: flex;
30
+ align-items: center;
31
+ flex: 0 0 var(--ob-datenavigator-height);
32
+ justify-content: center;
33
+
34
+ height: var(--ob-datenavigator-height);
35
+
36
+ cursor: pointer;
37
+ text-align: center;
38
+
39
+ &:hover:not(:disabled) {
40
+ background-color: #e3e3e3;
41
+ background-color: var(--block-header-button-hover);
42
+ }
43
+
44
+ &:disabled {
45
+ cursor: not-allowed;
46
+ color: rgba(0 0 0 / 0.2);
47
+ }
48
+ }
49
+
50
+ .ObDateNavigator-arrowLeft {
51
+ border-right: 1px solid #dddddd;
52
+ order: 1;
53
+ }
54
+
55
+ .ObDateNavigator-arrowRight {
56
+ border-left: 1px solid #dddddd;
57
+ order: 3;
58
+ }
59
+
60
+ .ObDateNavigator-date {
61
+ display: flex;
62
+ flex: 1 1 100%;
63
+ flex-direction: column;
64
+ justify-content: center;
65
+ order: 2;
66
+
67
+ height: var(--ob-datenavigator-height);
68
+
69
+ text-align: center;
70
+ }
71
+
72
+ .ObDateNavigator-today {
73
+ order: 4;
74
+ padding: 0 1rem;
75
+ height: var(--ob-datenavigator-height);
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ font-size: 0.875rem;
80
+ color: var(--brand-dark, #336699);
81
+ text-transform: uppercase;
82
+ cursor: pointer;
83
+
84
+ text-wrap: nowrap;
85
+
86
+ border-left: 1px solid #dddddd;
87
+
88
+ &:hover:not(:disabled) {
89
+ background-color: var(--block-header-button-hover);
90
+ }
91
+
92
+ &:focus-visible {
93
+ outline: 2px solid var(--brand-dark, #336699);
94
+ outline-offset: 2px;
95
+ }
96
+ }
@@ -1,4 +1,4 @@
1
- import "./index.scss";
1
+ import "./index.css";
2
2
 
3
3
  import { getLocalizedString } from "@olenbetong/appframe-core";
4
4
  import clsx from "clsx";
@@ -15,7 +15,7 @@ function Arrow({
15
15
  return (
16
16
  <button
17
17
  className={clsx(
18
- "ObDateNavigator-arrow",
18
+ "ObDateNavigator-arrow btn-reset",
19
19
  direction === "left" ? "ObDateNavigator-arrowLeft" : "ObDateNavigator-arrowRight",
20
20
  )}
21
21
  aria-label={direction === "left" ? getLocalizedString("Previous day") : getLocalizedString("Next day")}
@@ -52,19 +52,42 @@ const formatter = new Intl.DateTimeFormat(getUiCulture(), {
52
52
 
53
53
  const oneDay = 24 * 60 * 60 * 1000;
54
54
 
55
+ export type DateNavigatorProps = {
56
+ date?: Date | string | number;
57
+ defaultDate?: Date | string | number; // For default uncontrolled value
58
+ disableTodayButton?: boolean;
59
+ onChange?: (date: Date) => void;
60
+ minDate?: Date | string | number;
61
+ maxDate?: Date | string | number;
62
+ };
63
+
64
+ function sanitizeDate(date: Date | string | number): Date {
65
+ if (typeof date === "string" || typeof date === "number") {
66
+ let parsedDate = new Date(date);
67
+ if (Number.isNaN(parsedDate.getTime())) {
68
+ throw new Error(`Invalid date value: ${date}`);
69
+ }
70
+ return parsedDate;
71
+ } else if (date instanceof Date) {
72
+ if (Number.isNaN(date.getTime())) {
73
+ throw new Error(`Invalid date object: ${date}`);
74
+ }
75
+ return new Date(date.getTime()); // Return a copy of the date
76
+ } else {
77
+ throw new Error(`Unsupported date type: ${typeof date}`);
78
+ }
79
+ }
80
+
55
81
  export function DateNavigator({
56
82
  date: dateProp,
83
+ defaultDate,
84
+ disableTodayButton,
57
85
  onChange,
58
- minDate,
59
- maxDate,
60
- }: {
61
- date?: Date;
62
- onChange?: (date: Date) => void;
63
- minDate?: Date;
64
- maxDate?: Date;
65
- }) {
66
- let [internalDate, setInternalDate] = useState(new Date());
67
- let date = dateProp ?? internalDate;
86
+ minDate: minDateProp,
87
+ maxDate: maxDateProp,
88
+ }: DateNavigatorProps) {
89
+ let [internalDate, setInternalDate] = useState(() => (defaultDate ? sanitizeDate(defaultDate) : new Date()));
90
+ let date = dateProp ? sanitizeDate(dateProp) : internalDate;
68
91
  let dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
69
92
  let today = new Date();
70
93
  let todayUtc = Date.UTC(today.getFullYear(), today.getMonth(), today.getDate());
@@ -78,6 +101,8 @@ export function DateNavigator({
78
101
  return base;
79
102
  })();
80
103
 
104
+ let minDate = minDateProp && sanitizeDate(minDateProp);
105
+ let maxDate = maxDateProp && sanitizeDate(maxDateProp);
81
106
  let disablePrev = !!minDate && dateUtc <= Date.UTC(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
82
107
  let disableNext = !!maxDate && dateUtc >= Date.UTC(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate());
83
108
 
@@ -88,8 +113,8 @@ export function DateNavigator({
88
113
  newDate = new Date(maxDate); // Ensure we don't go above maxDate
89
114
  }
90
115
 
91
- if (onChange) onChange(newDate);
92
- else setInternalDate(newDate);
116
+ onChange?.(newDate);
117
+ setInternalDate(newDate);
93
118
  }
94
119
 
95
120
  function jumpToToday() {
@@ -148,9 +173,11 @@ export function DateNavigator({
148
173
  <Arrow direction="left" onClick={() => updateDate(new Date(dateUtc - oneDay))} disabled={disablePrev} />
149
174
  <div className="ObDateNavigator-date">{text}</div>
150
175
  <Arrow direction="right" onClick={() => updateDate(new Date(dateUtc + oneDay))} disabled={disableNext} />
151
- <button type="button" className="ObDateNavigator-today" onClick={jumpToToday}>
152
- {getLocalizedString("Today")}
153
- </button>
176
+ {!disableTodayButton && (
177
+ <button type="button" className="ObDateNavigator-today btn-reset" onClick={jumpToToday}>
178
+ {getLocalizedString("Today")}
179
+ </button>
180
+ )}
154
181
  <div aria-live="polite" ref={liveRef} style={{ position: "absolute", left: "-9999px" }} />
155
182
  </div>
156
183
  );
package/src/index.scss CHANGED
@@ -1,6 +1,6 @@
1
1
  @use "Checkbox/index.scss";
2
2
  @use "ColorCard/index.css" as index2;
3
- @use "DateNavigator/index.scss" as index3;
3
+ @use "DateNavigator/index.css" as index3;
4
4
  @use "LinkedCardList/index.scss" as index4;
5
5
  @use "PageBanner/index.scss" as index5;
6
6
  @use "ProgressBar/index.scss" as index6;
@@ -1,93 +0,0 @@
1
- @use "../styles/mixins";
2
-
3
- $date-select-height: 3rem;
4
-
5
- .ObDateNavigator-icon {
6
- display: inline-block;
7
-
8
- svg {
9
- width: 0.625em;
10
- position: relative;
11
- top: -1px;
12
- }
13
- }
14
-
15
- .ObDateNavigator-root {
16
- background-color: hsl(220, 20%, 96%);
17
- background-color: var(--block-header-color-bg);
18
- display: flex;
19
- font-size: 1rem;
20
- outline: none;
21
-
22
- &:focus-visible {
23
- outline: 2px solid var(--brand-dark, #336699);
24
- outline-offset: 2px;
25
- }
26
- }
27
-
28
- .ObDateNavigator-arrow {
29
- @include mixins.btn-reset;
30
- display: flex;
31
- align-items: center;
32
- flex: 0 0 $date-select-height;
33
- justify-content: center;
34
-
35
- height: $date-select-height;
36
-
37
- cursor: pointer;
38
- text-align: center;
39
-
40
- &:hover {
41
- background-color: #e3e3e3;
42
- background-color: var(--block-header-button-hover);
43
- }
44
- }
45
-
46
- .ObDateNavigator-arrowLeft {
47
- border-right: 1px solid #dddddd;
48
- order: 1;
49
- }
50
-
51
- .ObDateNavigator-arrowRight {
52
- border-left: 1px solid #dddddd;
53
- order: 3;
54
- }
55
-
56
- .ObDateNavigator-date {
57
- display: flex;
58
- flex: 1 1 100%;
59
- flex-direction: column;
60
- justify-content: center;
61
- order: 2;
62
-
63
- height: $date-select-height;
64
-
65
- text-align: center;
66
- }
67
-
68
- .ObDateNavigator-today {
69
- @include mixins.btn-reset;
70
- order: 4;
71
- padding: 0 1rem;
72
- height: $date-select-height;
73
- display: flex;
74
- align-items: center;
75
- justify-content: center;
76
- font-size: 0.875rem;
77
- color: var(--brand-dark, #336699);
78
- text-transform: uppercase;
79
- cursor: pointer;
80
-
81
- text-wrap: nowrap;
82
-
83
- border-left: 1px solid #dddddd;
84
-
85
- &:hover {
86
- background-color: var(--block-header-button-hover);
87
- }
88
-
89
- &:focus-visible {
90
- outline: 2px solid var(--brand-dark, #336699);
91
- outline-offset: 2px;
92
- }
93
- }