@iota/apps-ui-kit 0.9.5 → 0.10.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/CHANGELOG.md +18 -0
- package/dist/index.d.ts +55 -3
- package/dist/index.es.js +5697 -6536
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +36 -40
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +2 -1
- package/package.json +14 -18
- package/src/lib/components/atoms/badge/Badge.tsx +4 -3
- package/src/lib/components/atoms/badge/badge.classes.ts +3 -0
- package/src/lib/components/atoms/badge/badge.enums.ts +1 -0
- package/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx +1 -1
- package/src/lib/components/atoms/label-text/LabelText.tsx +1 -1
- package/src/lib/components/atoms/tooltip/Tooltip.tsx +2 -2
- package/src/lib/components/molecules/date-picker/DatePicker.tsx +412 -0
- package/src/lib/components/molecules/date-picker/date-picker.classes.ts +42 -0
- package/src/lib/components/molecules/date-picker/date-picker.constants.ts +23 -0
- package/src/lib/components/molecules/date-picker/date-picker.enums.ts +8 -0
- package/src/lib/components/molecules/date-picker/date-picker.helpers.ts +67 -0
- package/src/lib/components/molecules/date-picker/index.ts +5 -0
- package/src/lib/components/molecules/index.ts +1 -0
- package/src/lib/styles/components.css +89 -0
- package/src/lib/styles/variables/dark-variables.css +15 -0
- package/src/lib/styles/variables/light-variables.css +15 -0
- package/src/lib/styles/variables/names-variables.css +15 -0
- package/src/storybook/stories/design-tokens/{colors.stories.mdx → colors.mdx} +1 -1
- package/src/storybook/stories/design-tokens/{icons.stories.mdx → icons.mdx} +1 -1
- package/src/storybook/stories/design-tokens/{typeset.stories.mdx → typeset.mdx} +1 -1
- package/src/storybook/stories/design-tokens/{variable-spacing.stories.mdx → variable-spacing.mdx} +1 -1
- package/src/storybook/stories/molecules/DatePicker.stories.tsx +132 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright (c) 2026 IOTA Stiftung
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { DECADE_SIZE } from './date-picker.constants';
|
|
5
|
+
import { DatePickerFormat } from './date-picker.enums';
|
|
6
|
+
|
|
7
|
+
export function isSameDay(a: Date, b: Date): boolean {
|
|
8
|
+
return (
|
|
9
|
+
a.getFullYear() === b.getFullYear() &&
|
|
10
|
+
a.getMonth() === b.getMonth() &&
|
|
11
|
+
a.getDate() === b.getDate()
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function startOfDay(date: Date): Date {
|
|
16
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Returns true when date falls outside the [min, max] inclusive range. */
|
|
20
|
+
export function isDateDisabled(date: Date, min?: Date, max?: Date): boolean {
|
|
21
|
+
const d = startOfDay(date);
|
|
22
|
+
if (min && d < startOfDay(min)) return true;
|
|
23
|
+
if (max && d > startOfDay(max)) return true;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Returns true when every day in year is outside [min, max]. */
|
|
28
|
+
export function isYearDisabled(year: number, min?: Date, max?: Date): boolean {
|
|
29
|
+
if (min && new Date(year, 11, 31) < startOfDay(min)) return true;
|
|
30
|
+
if (max && new Date(year, 0, 1) > startOfDay(max)) return true;
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatDate(date: Date, format: DatePickerFormat): string {
|
|
35
|
+
const year = String(date.getFullYear());
|
|
36
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
37
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
38
|
+
switch (format) {
|
|
39
|
+
case DatePickerFormat.DayMonthYear:
|
|
40
|
+
return `${day}/${month}/${year}`;
|
|
41
|
+
case DatePickerFormat.MonthDayYear:
|
|
42
|
+
return `${month}/${day}/${year}`;
|
|
43
|
+
case DatePickerFormat.YearMonthDay:
|
|
44
|
+
return `${year}/${month}/${day}`;
|
|
45
|
+
default:
|
|
46
|
+
return `${day}/${month}/${year}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Builds the 6×7 grid of dates for the calendar day view
|
|
52
|
+
* starts on Sunday of the week containing the 1st of the month.
|
|
53
|
+
*/
|
|
54
|
+
export function buildCalendarGrid(year: number, month: number): Date[] {
|
|
55
|
+
const firstDay = new Date(year, month, 1);
|
|
56
|
+
const startOffset = firstDay.getDay(); // 0 = Sunday
|
|
57
|
+
const grid: Date[] = [];
|
|
58
|
+
for (let i = -startOffset; i < 42 - startOffset; i++) {
|
|
59
|
+
grid.push(new Date(year, month, 1 + i));
|
|
60
|
+
}
|
|
61
|
+
return grid;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Returns the first year of the decade that contains year */
|
|
65
|
+
export function decadeStart(year: number): number {
|
|
66
|
+
return Math.floor(year / DECADE_SIZE) * DECADE_SIZE;
|
|
67
|
+
}
|
|
@@ -26,6 +26,14 @@
|
|
|
26
26
|
border-color: var(--badge-border-color-soft);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
.badge-border-color-outlined {
|
|
30
|
+
border-color: theme('colors.iota-neutral.40');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.badge-ring-outlined {
|
|
34
|
+
box-shadow: inset 0 0 0 1px theme('colors.iota-neutral.40');
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
.badge-text-color-neutral {
|
|
30
38
|
color: var(--badge-text-color-neutral);
|
|
31
39
|
}
|
|
@@ -724,6 +732,87 @@
|
|
|
724
732
|
color: var(--table-text-color);
|
|
725
733
|
}
|
|
726
734
|
|
|
735
|
+
/* DATE PICKER */
|
|
736
|
+
.date-picker-trigger-text-color {
|
|
737
|
+
color: var(--date-picker-text-color);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.date-picker-trigger-placeholder-color {
|
|
741
|
+
color: var(--date-picker-trigger-placeholder-color);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.date-picker-trigger-border-color {
|
|
745
|
+
border-color: var(--date-picker-border-color);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
.date-picker-trigger-border-hover-color {
|
|
749
|
+
border-color: var(--date-picker-trigger-border-hover-color);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.date-picker-trigger-border-focus-color {
|
|
753
|
+
border-color: var(--date-picker-focus-color);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.date-picker-trigger-border-error-color {
|
|
757
|
+
border-color: var(--date-picker-trigger-border-error-color);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.date-picker-calendar-bg {
|
|
761
|
+
background-color: var(--date-picker-calendar-bg);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
.date-picker-calendar-border-color {
|
|
765
|
+
border-color: var(--date-picker-border-color);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
.date-picker-header-text-color {
|
|
769
|
+
color: var(--date-picker-text-color);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
.date-picker-nav-icon-color {
|
|
773
|
+
color: var(--date-picker-muted-text-color);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
.date-picker-nav-bg-hover:enabled:hover {
|
|
777
|
+
background-color: var(--date-picker-hover-bg);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.date-picker-weekday-text-color {
|
|
781
|
+
color: var(--date-picker-muted-text-color);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
.date-picker-day-text-color {
|
|
785
|
+
color: var(--date-picker-text-color);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.date-picker-day-bg-hover:enabled:hover {
|
|
789
|
+
background-color: var(--date-picker-hover-bg);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.date-picker-day-text-color-hover:enabled:hover {
|
|
793
|
+
color: var(--date-picker-text-color);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.date-picker-day-bg-selected {
|
|
797
|
+
background-color: var(--date-picker-day-bg-selected);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.date-picker-day-text-selected {
|
|
801
|
+
color: var(--date-picker-day-text-selected);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.date-picker-day-today-ring {
|
|
805
|
+
box-shadow: inset 0 0 0 1.5px var(--date-picker-focus-color);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.date-picker-day-text-disabled {
|
|
809
|
+
color: var(--date-picker-day-text-disabled);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.date-picker-day-text-outside-month {
|
|
813
|
+
color: var(--date-picker-day-text-outside-month);
|
|
814
|
+
}
|
|
815
|
+
|
|
727
816
|
/* DIALOG */
|
|
728
817
|
.dialog-outline {
|
|
729
818
|
outline: var(--dialog-outline);
|
|
@@ -256,6 +256,21 @@
|
|
|
256
256
|
/* TABLE */
|
|
257
257
|
--table-text-color: theme('colors.iota-neutral.60');
|
|
258
258
|
|
|
259
|
+
/* DATE PICKER */
|
|
260
|
+
--date-picker-text-color: theme('colors.iota-neutral.92');
|
|
261
|
+
--date-picker-trigger-placeholder-color: rgba(136, 146, 161, 0.4);
|
|
262
|
+
--date-picker-border-color: theme('colors.iota-neutral.20');
|
|
263
|
+
--date-picker-trigger-border-hover-color: theme('colors.iota-neutral.60');
|
|
264
|
+
--date-picker-focus-color: theme('colors.iota-primary.80');
|
|
265
|
+
--date-picker-trigger-border-error-color: theme('colors.iota-error.80');
|
|
266
|
+
--date-picker-calendar-bg: theme('colors.iota-neutral.6');
|
|
267
|
+
--date-picker-muted-text-color: theme('colors.iota-neutral.60');
|
|
268
|
+
--date-picker-hover-bg: theme('colors.iota-neutral.12');
|
|
269
|
+
--date-picker-day-bg-selected: theme('colors.iota-primary.30');
|
|
270
|
+
--date-picker-day-text-selected: theme('colors.iota-primary.100');
|
|
271
|
+
--date-picker-day-text-disabled: theme('colors.iota-neutral.60');
|
|
272
|
+
--date-picker-day-text-outside-month: theme('colors.iota-neutral.40');
|
|
273
|
+
|
|
259
274
|
/* DIALOG */
|
|
260
275
|
--dialog-outline: none;
|
|
261
276
|
--dialog-overlay-bg: theme('colors.shader-neutral-light.48');
|
|
@@ -270,6 +270,21 @@
|
|
|
270
270
|
/* TABLE */
|
|
271
271
|
--table-text-color: theme('colors.iota-neutral.40');
|
|
272
272
|
|
|
273
|
+
/* DATE PICKER */
|
|
274
|
+
--date-picker-text-color: theme('colors.iota-neutral.10');
|
|
275
|
+
--date-picker-trigger-placeholder-color: rgba(84, 94, 110, 0.4);
|
|
276
|
+
--date-picker-border-color: theme('colors.iota-neutral.80');
|
|
277
|
+
--date-picker-trigger-border-hover-color: theme('colors.iota-neutral.50');
|
|
278
|
+
--date-picker-focus-color: theme('colors.iota-primary.30');
|
|
279
|
+
--date-picker-trigger-border-error-color: theme('colors.iota-error.30');
|
|
280
|
+
--date-picker-calendar-bg: theme('colors.iota-neutral.100');
|
|
281
|
+
--date-picker-muted-text-color: theme('colors.iota-neutral.40');
|
|
282
|
+
--date-picker-hover-bg: theme('colors.iota-neutral.92');
|
|
283
|
+
--date-picker-day-bg-selected: theme('colors.iota-primary.30');
|
|
284
|
+
--date-picker-day-text-selected: theme('colors.iota-primary.100');
|
|
285
|
+
--date-picker-day-text-disabled: theme('colors.iota-neutral.40');
|
|
286
|
+
--date-picker-day-text-outside-month: theme('colors.iota-neutral.60');
|
|
287
|
+
|
|
273
288
|
/* DIALOG */
|
|
274
289
|
--dialog-outline: none;
|
|
275
290
|
--dialog-overlay-bg: theme('colors.shader-neutral-light.48');
|
|
@@ -267,4 +267,19 @@
|
|
|
267
267
|
|
|
268
268
|
/* TABLE */
|
|
269
269
|
--table-text-color: theme('colors.names-neutral.70');
|
|
270
|
+
|
|
271
|
+
/* DATE PICKER */
|
|
272
|
+
--date-picker-text-color: theme('colors.names-neutral.92');
|
|
273
|
+
--date-picker-trigger-placeholder-color: rgba(136, 146, 161, 0.4);
|
|
274
|
+
--date-picker-border-color: theme('colors.names-neutral.20');
|
|
275
|
+
--date-picker-trigger-border-hover-color: theme('colors.names-neutral.60');
|
|
276
|
+
--date-picker-focus-color: theme('colors.names-primary.80');
|
|
277
|
+
--date-picker-trigger-border-error-color: theme('colors.names-error.80');
|
|
278
|
+
--date-picker-calendar-bg: theme('colors.names-neutral.6');
|
|
279
|
+
--date-picker-muted-text-color: theme('colors.names-neutral.70');
|
|
280
|
+
--date-picker-hover-bg: theme('colors.names-neutral.12');
|
|
281
|
+
--date-picker-day-bg-selected: theme('colors.names-primary.30');
|
|
282
|
+
--date-picker-day-text-selected: theme('colors.names-primary.100');
|
|
283
|
+
--date-picker-day-text-disabled: theme('colors.names-neutral.60');
|
|
284
|
+
--date-picker-day-text-outside-month: theme('colors.names-neutral.40');
|
|
270
285
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Meta, Title, IconGallery, IconItem } from '@storybook/blocks';
|
|
2
|
+
import { Meta, Title, IconGallery, IconItem } from '@storybook/addon-docs/blocks';
|
|
3
3
|
import * as Icons from '@iota/apps-ui-icons';
|
|
4
4
|
import { DocsSyncTheme } from '../components';
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Meta, Typeset, Unstyled } from '@storybook/blocks';
|
|
1
|
+
import { Meta, Typeset, Unstyled } from '@storybook/addon-docs/blocks';
|
|
2
2
|
import { TYPESETS } from '../../constants';
|
|
3
3
|
import { TypeSet, TypeSetItem } from '../../blocks';
|
|
4
4
|
import { DocsSyncTheme } from '../components';
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Copyright (c) 2026 IOTA Stiftung
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { DatePicker, DatePickerFormat } from '@/components/molecules/date-picker';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof DatePicker> = {
|
|
9
|
+
component: DatePicker,
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'centered',
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
dateFormat: {
|
|
16
|
+
control: { type: 'select' },
|
|
17
|
+
options: Object.values(DatePickerFormat),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
} satisfies Meta<typeof DatePicker>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
export const Default: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
label: 'Select Date',
|
|
29
|
+
caption: 'Choose a date from the calendar',
|
|
30
|
+
placeholder: 'DD/MM/YYYY',
|
|
31
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
32
|
+
},
|
|
33
|
+
render: (args) => {
|
|
34
|
+
const [date, setDate] = useState<Date | undefined>(undefined);
|
|
35
|
+
return (
|
|
36
|
+
<div className="w-72 pb-80">
|
|
37
|
+
<DatePicker {...args} value={date} onChange={setDate} />
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const WithDateFormat: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
label: 'Format DD/MM/YYYY',
|
|
46
|
+
caption: 'Change the date format from the controls ',
|
|
47
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
48
|
+
},
|
|
49
|
+
render: (args) => {
|
|
50
|
+
const [date, setDate] = useState<Date | undefined>(new Date(2026, 3, 15));
|
|
51
|
+
return (
|
|
52
|
+
<div className="w-72 pb-80">
|
|
53
|
+
<DatePicker {...args} value={date} onChange={setDate} />
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const WithMinMaxLimitsInclusive: Story = {
|
|
60
|
+
name: 'Min & Max (inclusive)',
|
|
61
|
+
args: {
|
|
62
|
+
label: 'April 2026 only',
|
|
63
|
+
caption: 'Min = Apr 1 · Max = Apr 30 · both selectable',
|
|
64
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
65
|
+
},
|
|
66
|
+
render: (args) => {
|
|
67
|
+
const minDate = new Date(2026, 3, 1); // April 1 2026
|
|
68
|
+
const maxDate = new Date(2026, 3, 30); // April 30 2026
|
|
69
|
+
const [date, setDate] = useState<Date | undefined>(undefined);
|
|
70
|
+
return (
|
|
71
|
+
<div className="w-72 pb-80">
|
|
72
|
+
<DatePicker
|
|
73
|
+
{...args}
|
|
74
|
+
value={date}
|
|
75
|
+
onChange={setDate}
|
|
76
|
+
minDate={minDate}
|
|
77
|
+
maxDate={maxDate}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const YearPickerNavigation: Story = {
|
|
85
|
+
name: 'Year picker (click "Month Year")',
|
|
86
|
+
args: {
|
|
87
|
+
label: 'Birth date',
|
|
88
|
+
caption: 'Click "April 2026" header to jump to any year',
|
|
89
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
90
|
+
},
|
|
91
|
+
render: (args) => {
|
|
92
|
+
const [date, setDate] = useState<Date | undefined>(undefined);
|
|
93
|
+
return (
|
|
94
|
+
<div className="w-72 pb-80">
|
|
95
|
+
<DatePicker {...args} value={date} onChange={setDate} />
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const WithError: Story = {
|
|
102
|
+
args: {
|
|
103
|
+
label: 'Expiry Date',
|
|
104
|
+
errorMessage: 'Date is required',
|
|
105
|
+
placeholder: 'DD/MM/YYYY',
|
|
106
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
107
|
+
},
|
|
108
|
+
render: (args) => {
|
|
109
|
+
const [date, setDate] = useState<Date | undefined>(undefined);
|
|
110
|
+
return (
|
|
111
|
+
<div className="w-72 pb-80">
|
|
112
|
+
<DatePicker {...args} value={date} onChange={setDate} />
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const Disabled: Story = {
|
|
119
|
+
args: {
|
|
120
|
+
label: 'Locked Date',
|
|
121
|
+
caption: 'This field is disabled',
|
|
122
|
+
disabled: true,
|
|
123
|
+
dateFormat: DatePickerFormat.DayMonthYear,
|
|
124
|
+
},
|
|
125
|
+
render: (args) => {
|
|
126
|
+
return (
|
|
127
|
+
<div className="w-72">
|
|
128
|
+
<DatePicker {...args} value={new Date(2026, 0, 1)} />
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
};
|