webcake-ui-kit 1.1.29 → 1.1.31

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 (29) hide show
  1. package/package.json +7 -2
  2. package/src/components/date-picker/CalendarPanel.vue +154 -0
  3. package/src/components/date-picker/CalendarView.vue +104 -0
  4. package/src/components/date-picker/DatePicker.vue +587 -0
  5. package/src/components/date-picker/PanelFooter.vue +45 -0
  6. package/src/components/date-picker/PanelHeader.vue +102 -0
  7. package/src/components/date-picker/TimePanel.vue +98 -0
  8. package/src/components/date-picker/calendar-panel.css +36 -0
  9. package/src/components/date-picker/calendar-view.css +134 -0
  10. package/src/components/date-picker/calendar.js +116 -0
  11. package/src/components/date-picker/date-picker.css +95 -0
  12. package/src/components/date-picker/dayjs.js +34 -0
  13. package/src/components/date-picker/panel-footer.css +42 -0
  14. package/src/components/date-picker/panel-header.css +71 -0
  15. package/src/components/date-picker/time-panel.css +63 -0
  16. package/src/components/input/input.css +5 -0
  17. package/src/components/menu/menu.css +0 -1
  18. package/src/components/message/Message.vue +72 -0
  19. package/src/components/message/MessageContainer.vue +200 -0
  20. package/src/components/message/message-container.css +108 -0
  21. package/src/components/message/message.css +69 -0
  22. package/src/components/message/message.js +133 -0
  23. package/src/components/progress/Progress.vue +42 -0
  24. package/src/components/progress/progress.css +15 -0
  25. package/src/components/radio/Radio.vue +1 -1
  26. package/src/components/radio-group/RadioGroup.vue +2 -2
  27. package/src/components/table/Table.vue +30 -21
  28. package/src/components/table/table.css +18 -2
  29. package/src/index.js +5 -0
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="ui-cal-header">
3
+ <div class="ui-cal-header__nav ui-cal-header__nav--prev">
4
+ <WkButton v-if="showYearJump" variant="ghost" size="xs" aria-label="Previous year" @click="$emit('prev-year')">
5
+ <template #icon><WkiChevronsLeft :size="16" /></template>
6
+ </WkButton>
7
+ <WkButton variant="ghost" size="xs" :disabled="!canPrev" aria-label="Previous month" @click="$emit('prev')">
8
+ <template #icon><WkiChevronLeft :size="16" /></template>
9
+ </WkButton>
10
+ </div>
11
+
12
+ <div class="ui-cal-header__labels">
13
+ <div v-for="(panel, i) in panels" :key="i" class="ui-cal-header__group">
14
+ <!-- Month: WkSelect when opted-in, otherwise the clickable text label. -->
15
+ <span v-if="showSelectMonth" class="ui-cal-header__select ui-cal-header__select--month">
16
+ <WkSelect
17
+ size="xs"
18
+ :value="String(panel.month)"
19
+ :options="monthOptions"
20
+ @change="m => $emit('set-month', { index: i, month: Number(m) })"
21
+ />
22
+ </span>
23
+ <button
24
+ v-else
25
+ type="button"
26
+ :class="[
27
+ 'ui-cal-header__label',
28
+ showSelectYear && !showSelectMonth && 'ui-cal-header__label_month_not_select'
29
+ ]"
30
+ @click="$emit('label-click', { index: i, part: 'month' })"
31
+ >
32
+ {{ monthName(panel.month) }}
33
+ </button>
34
+
35
+ <!-- Year: WkSelect when opted-in, otherwise the clickable text label. -->
36
+ <span v-if="showSelectYear" class="ui-cal-header__select ui-cal-header__select--year">
37
+ <WkSelect
38
+ size="xs"
39
+ :value="String(panel.year)"
40
+ :options="yearOptions"
41
+ @change="y => $emit('set-year', { index: i, year: Number(y) })"
42
+ />
43
+ </span>
44
+ <button
45
+ v-else
46
+ type="button"
47
+ :class="[
48
+ 'ui-cal-header__label',
49
+ !showSelectYear && showSelectMonth && 'ui-cal-header__label_year_not_select'
50
+ ]"
51
+ @click="$emit('label-click', { index: i, part: 'year' })"
52
+ >
53
+ {{ panel.year }}
54
+ </button>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="ui-cal-header__nav ui-cal-header__nav--next">
59
+ <WkButton variant="ghost" size="xs" :disabled="!canNext" aria-label="Next month" @click="$emit('next')">
60
+ <template #icon><WkiChevronRight :size="16" /></template>
61
+ </WkButton>
62
+ <WkButton v-if="showYearJump" variant="ghost" size="xs" aria-label="Next year" @click="$emit('next-year')">
63
+ <template #icon><WkiChevronsRight :size="16" /></template>
64
+ </WkButton>
65
+ </div>
66
+ </div>
67
+ </template>
68
+
69
+ <script>
70
+ import WkButton from '../button/Button.vue'
71
+ import WkSelect from '../select/Select.vue'
72
+ import { WkiChevronLeft, WkiChevronRight, WkiChevronsLeft, WkiChevronsRight } from '../../icons'
73
+
74
+ export default {
75
+ name: 'PanelHeader',
76
+ components: { WkButton, WkSelect, WkiChevronLeft, WkiChevronRight, WkiChevronsLeft, WkiChevronsRight },
77
+ props: {
78
+ // One entry per visible month: { month: 0-11, year: Number }.
79
+ panels: { type: Array, default: () => [] },
80
+ // Localized month names as select options: [{ label, value: '0'..'11' }].
81
+ monthOptions: { type: Array, default: () => [] },
82
+ // Selectable years: [{ label, value: 'YYYY' }].
83
+ yearOptions: { type: Array, default: () => [] },
84
+ // Swap the month / year label for a WkSelect dropdown.
85
+ showSelectMonth: { type: Boolean, default: false },
86
+ showSelectYear: { type: Boolean, default: false },
87
+ canPrev: { type: Boolean, default: true },
88
+ canNext: { type: Boolean, default: true },
89
+ // Double-chevron year jump (used by month/year drill views in Phase 2).
90
+ showYearJump: { type: Boolean, default: false }
91
+ },
92
+ emits: ['prev', 'next', 'prev-year', 'next-year', 'set-month', 'set-year', 'label-click'],
93
+ methods: {
94
+ monthName(month) {
95
+ const opt = this.monthOptions[month]
96
+ return opt ? opt.label : month + 1
97
+ }
98
+ }
99
+ }
100
+ </script>
101
+
102
+ <style src="./panel-header.css" scoped></style>
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <div class="ui-time-panel">
3
+ <div v-for="col in columns" :key="col.key" class="ui-time-panel__col" role="listbox" :aria-label="col.key">
4
+ <button
5
+ v-for="opt in col.options"
6
+ :key="opt"
7
+ type="button"
8
+ class="ui-time-panel__opt"
9
+ :class="{ 'is-active': opt === col.value, 'is-disabled': col.disabled.indexOf(opt) !== -1 }"
10
+ :disabled="col.disabled.indexOf(opt) !== -1"
11
+ :aria-selected="opt === col.value ? 'true' : 'false'"
12
+ @click="onPick(col.key, opt)"
13
+ >
14
+ {{ pad(opt) }}
15
+ </button>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ export default {
22
+ name: 'TimePanel',
23
+ props: {
24
+ // { hour, minute, second } — 24-hour numeric parts.
25
+ value: {
26
+ type: Object,
27
+ default: () => ({ hour: 0, minute: 0, second: 0 })
28
+ },
29
+ showSeconds: { type: Boolean, default: false },
30
+ hourStep: { type: Number, default: 1 },
31
+ minuteStep: { type: Number, default: 1 },
32
+ secondStep: { type: Number, default: 1 },
33
+ // () => { disabledHours?, disabledMinutes?(h), disabledSeconds?(h,m) }
34
+ disabledTime: { type: Function, default: null }
35
+ },
36
+ emits: ['change'],
37
+ computed: {
38
+ rules() {
39
+ return (typeof this.disabledTime === 'function' && this.disabledTime()) || {}
40
+ },
41
+ columns() {
42
+ const v = this.value || {}
43
+ const h = v.hour || 0
44
+ const m = v.minute || 0
45
+ const cols = [
46
+ {
47
+ key: 'hour',
48
+ value: h,
49
+ options: this.range(24, this.hourStep),
50
+ disabled: this.callRule(this.rules.disabledHours)
51
+ },
52
+ {
53
+ key: 'minute',
54
+ value: m,
55
+ options: this.range(60, this.minuteStep),
56
+ disabled: this.callRule(this.rules.disabledMinutes, h)
57
+ }
58
+ ]
59
+ if (this.showSeconds) {
60
+ cols.push({
61
+ key: 'second',
62
+ value: v.second || 0,
63
+ options: this.range(60, this.secondStep),
64
+ disabled: this.callRule(this.rules.disabledSeconds, h, m)
65
+ })
66
+ }
67
+ return cols
68
+ }
69
+ },
70
+ methods: {
71
+ range(count, step) {
72
+ const out = []
73
+ const s = step > 0 ? step : 1
74
+ for (let i = 0; i < count; i += s) out.push(i)
75
+ return out
76
+ },
77
+ callRule(fn, a, b) {
78
+ if (typeof fn !== 'function') return []
79
+ const r = fn(a, b)
80
+ return Array.isArray(r) ? r : []
81
+ },
82
+ pad(n) {
83
+ return n < 10 ? '0' + n : '' + n
84
+ },
85
+ onPick(key, opt) {
86
+ const next = {
87
+ hour: this.value.hour || 0,
88
+ minute: this.value.minute || 0,
89
+ second: this.value.second || 0
90
+ }
91
+ next[key] = opt
92
+ this.$emit('change', next)
93
+ }
94
+ }
95
+ }
96
+ </script>
97
+
98
+ <style src="./time-panel.css" scoped></style>
@@ -0,0 +1,36 @@
1
+ .ui-cal-panel {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-sm);
5
+ padding: var(--spacing-md);
6
+ background: var(--card);
7
+ font-family: var(--font-family-body);
8
+ border-radius: var(--rounded-xl);
9
+ }
10
+
11
+ .ui-cal-panel__main {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: var(--spacing-md);
15
+ }
16
+
17
+ .ui-cal-panel__body {
18
+ display: flex;
19
+ gap: var(--spacing-lg);
20
+ }
21
+
22
+ /* Months sit side by side; each grid is 7×36px wide. */
23
+ .ui-cal-panel__months {
24
+ display: flex;
25
+ gap: var(--spacing-md);
26
+ }
27
+
28
+ .ui-cal-panel__month {
29
+ flex-shrink: 0;
30
+ }
31
+
32
+ /* Time column divided from the calendar. */
33
+ .ui-cal-panel__time {
34
+ padding-left: var(--spacing-xs);
35
+ border-left: 1px solid var(--border-primary);
36
+ }
@@ -0,0 +1,134 @@
1
+ .ui-cal-view {
2
+ display: inline-flex;
3
+ flex-direction: column;
4
+ gap: var(--spacing-2xs);
5
+ font-family: var(--font-family-body);
6
+ }
7
+
8
+ /* Weekday header row — 7 fixed 36px tracks, muted labels. */
9
+ .ui-cal-view__weekdays {
10
+ display: grid;
11
+ grid-template-columns: repeat(7, 32px);
12
+ }
13
+
14
+ .ui-cal-view__weekday {
15
+ height: 32px;
16
+ width: 32px;
17
+ display: inline-flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ color: var(--muted-fg);
21
+ font-size: var(--paragraph-small-font-size);
22
+ line-height: var(--paragraph-small-line-height);
23
+ }
24
+
25
+ /*
26
+ * Day grid — 7 columns, cells butt together horizontally (column-gap 0) so the
27
+ * range band reads as one continuous strip; a small row-gap keeps weeks legible.
28
+ */
29
+ .ui-cal-view__grid {
30
+ display: grid;
31
+ grid-template-columns: repeat(7, 32px);
32
+ row-gap: 1px;
33
+ column-gap: 0;
34
+ }
35
+
36
+ .ui-cal-cell {
37
+ position: relative;
38
+ width: 32px;
39
+ height: 32px;
40
+ padding: 0;
41
+ border: 0;
42
+ background: transparent;
43
+ cursor: pointer;
44
+ font-family: inherit;
45
+ font-size: var(--paragraph-small-font-size);
46
+ line-height: var(--paragraph-small-line-height);
47
+ color: var(--primary-fg);
48
+ }
49
+
50
+ /*
51
+ * Range band layer (::before) sits behind the number. Full-width for interior
52
+ * days so neighbours connect; half-width toward the range on the endpoints.
53
+ */
54
+ .ui-cal-cell::before {
55
+ content: '';
56
+ position: absolute;
57
+ top: 0px;
58
+ bottom: 0px;
59
+ left: 0;
60
+ right: 0;
61
+ background: transparent;
62
+ z-index: 0;
63
+ }
64
+
65
+ .ui-cal-cell.is-in-range::before {
66
+ background: var(--accent-1);
67
+ }
68
+
69
+ .ui-cal-cell.is-range-left::before {
70
+ left: 50%;
71
+ right: 0;
72
+ background: var(--brand-100);
73
+ }
74
+
75
+ .ui-cal-cell.is-range-right::before {
76
+ left: 0;
77
+ right: 50%;
78
+ background: var(--brand-100);
79
+ }
80
+
81
+ /* The visible day chip — rounded, holds hover / selected fills and the number. */
82
+ .ui-cal-cell__inner {
83
+ position: relative;
84
+ z-index: 1;
85
+ display: inline-flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ width: 32px;
89
+ height: 32px;
90
+ border-radius: var(--rounded-lg);
91
+ transition:
92
+ background-color 0.12s ease,
93
+ color 0.12s ease;
94
+ }
95
+
96
+ .ui-cal-cell:hover:not(.is-disabled):not(.is-selected) .ui-cal-cell__inner {
97
+ background: var(--accent-1);
98
+ }
99
+
100
+ .ui-cal-cell.is-outside {
101
+ color: var(--muted-fg);
102
+ }
103
+
104
+ .ui-cal-cell.is-today .ui-cal-cell__inner {
105
+ box-shadow: inset 0 0 0 1px var(--border-brand);
106
+ }
107
+
108
+ .ui-cal-cell.is-selected .ui-cal-cell__inner {
109
+ background: var(--primary-brand-bg);
110
+ color: var(--inverse-fg);
111
+ }
112
+
113
+ /* Selected endpoint wins over the today ring. */
114
+ .ui-cal-cell.is-selected.is-today .ui-cal-cell__inner {
115
+ box-shadow: none;
116
+ }
117
+
118
+ .ui-cal-cell.is-disabled {
119
+ color: var(--muted-fg);
120
+ cursor: not-allowed;
121
+ }
122
+
123
+ .ui-cal-cell.is-disabled .ui-cal-cell__inner {
124
+ background: transparent;
125
+ }
126
+
127
+ .ui-cal-cell.is-focus:focus-visible {
128
+ outline: none;
129
+ }
130
+
131
+ .ui-cal-cell.is-focus:focus-visible .ui-cal-cell__inner {
132
+ outline: 2px solid var(--focus-ring);
133
+ outline-offset: 1px;
134
+ }
@@ -0,0 +1,116 @@
1
+ // Pure calendar math for the date-picker — no Vue, no component state.
2
+ //
3
+ // Everything here operates on plain values (ISO 'YYYY-MM-DD' strings, Day.js
4
+ // instances, plain option objects) so it can be unit-tested in isolation and
5
+ // reused by the week/month/quarter/year panels in Phase 2. The picker stores
6
+ // its selection as ISO strings internally (stable identity, no deep-reactive
7
+ // Day.js objects in `data`) and only converts to Date/formatted output at the
8
+ // component boundary.
9
+ import dayjs from './dayjs.js'
10
+
11
+ export const ISO = 'YYYY-MM-DD'
12
+
13
+ // Normalize any accepted value (Date | ISO/formatted string | Day.js | number)
14
+ // into a Day.js instance, or null when empty/invalid. `format` is consulted for
15
+ // string parsing so a custom `format` prop round-trips.
16
+ export function toDayjs(value, format) {
17
+ if (value == null || value === '') return null
18
+ if (dayjs.isDayjs(value)) return value.isValid() ? value : null
19
+ if (value instanceof Date) {
20
+ const d = dayjs(value)
21
+ return d.isValid() ? d : null
22
+ }
23
+ if (typeof value === 'number') {
24
+ const d = dayjs(value)
25
+ return d.isValid() ? d : null
26
+ }
27
+ // string: try the explicit format first, then ISO, then loose parse.
28
+ if (typeof value === 'string') {
29
+ if (format) {
30
+ const byFmt = dayjs(value, format)
31
+ if (byFmt.isValid()) return byFmt
32
+ }
33
+ const byIso = dayjs(value, ISO)
34
+ if (byIso.isValid()) return byIso
35
+ const loose = dayjs(value)
36
+ return loose.isValid() ? loose : null
37
+ }
38
+ return null
39
+ }
40
+
41
+ // Day.js → canonical ISO date key (drops time; the day grid keys on this).
42
+ export function toISO(value, format) {
43
+ const d = toDayjs(value, format)
44
+ return d ? d.format(ISO) : null
45
+ }
46
+
47
+ // Is `d` (Day.js) outside the allowed window / vetoed by disabledDate(Date)?
48
+ export function isDateDisabled(d, opts) {
49
+ if (!d) return true
50
+ const o = opts || {}
51
+ if (o.minDate && d.isBefore(o.minDate, 'day')) return true
52
+ if (o.maxDate && d.isAfter(o.maxDate, 'day')) return true
53
+ if (typeof o.disabledDate === 'function' && o.disabledDate(d.toDate())) return true
54
+ return false
55
+ }
56
+
57
+ // Locale-aware weekday header labels, rotated to `weekStart` (0 = Sunday).
58
+ // Uses Day.js localeData min-weekday names ('Su','Mo',...).
59
+ export function weekdayLabels(weekStart, locale) {
60
+ const base = (locale ? dayjs().locale(locale) : dayjs()).localeData().weekdaysMin()
61
+ const out = []
62
+ for (let i = 0; i < 7; i++) out.push(base[(i + weekStart) % 7])
63
+ return out
64
+ }
65
+
66
+ // Build the 6×7 (42-cell) day grid for the month containing `viewDate`.
67
+ // `weekStart` rotates the leading offset. Cells outside the view month are
68
+ // flagged `outside` (rendered muted) but remain selectable unless disabled.
69
+ export function buildDayMatrix(viewDate, weekStart, opts) {
70
+ const ws = weekStart || 0
71
+ const first = viewDate.startOf('month')
72
+ const offset = (first.day() - ws + 7) % 7
73
+ const start = first.subtract(offset, 'day')
74
+ const today = dayjs()
75
+ const month = viewDate.month()
76
+ const cells = []
77
+ for (let i = 0; i < 35; i++) {
78
+ const d = start.add(i, 'day')
79
+ const dow = d.day()
80
+ cells.push({
81
+ iso: d.format(ISO),
82
+ day: d.date(),
83
+ outside: d.month() !== month,
84
+ today: d.isSame(today, 'day'),
85
+ weekend: dow === 0 || dow === 6,
86
+ disabled: isDateDisabled(d, opts)
87
+ })
88
+ }
89
+ return cells
90
+ }
91
+
92
+ // Order two ISO keys ascending, tolerating either being null.
93
+ export function orderISO(a, b) {
94
+ if (a == null) return { start: b, end: b }
95
+ if (b == null) return { start: a, end: a }
96
+ return a <= b ? { start: a, end: b } : { start: b, end: a }
97
+ }
98
+
99
+ // Position of a cell within an active range [start,end] (both ISO), used to pick
100
+ // the connected-band radius: 'single' | 'left' | 'middle' | 'right' | null.
101
+ export function rangePosition(iso, start, end) {
102
+ if (!start && !end) return null
103
+ const s = start
104
+ const e = end || start
105
+ if (s === e) return iso === s ? 'single' : null
106
+ if (iso === s) return 'left'
107
+ if (iso === e) return 'right'
108
+ if (iso > s && iso < e) return 'middle'
109
+ return null
110
+ }
111
+
112
+ // True when `iso` sits strictly inside (start,end) — the range fill band.
113
+ export function isWithinRange(iso, start, end) {
114
+ if (!start || !end || start === end) return false
115
+ return iso > start && iso < end
116
+ }
@@ -0,0 +1,95 @@
1
+ .ui-date-picker {
2
+ display: inline-block;
3
+ }
4
+
5
+ .ui-date-picker__trigger {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: var(--spacing-xs);
9
+ width: 100%;
10
+ min-width: 200px;
11
+ box-sizing: border-box;
12
+ height: 36px;
13
+ padding: 0 var(--spacing-sm);
14
+ background: var(--input);
15
+ border: 1px solid var(--border-primary);
16
+ border-radius: var(--radius);
17
+ color: var(--primary-fg);
18
+ font-family: var(--font-family-body);
19
+ font-size: var(--paragraph-small-font-size);
20
+ line-height: var(--paragraph-small-line-height);
21
+ cursor: pointer;
22
+ transition:
23
+ border-color 0.12s ease,
24
+ box-shadow 0.12s ease;
25
+ }
26
+
27
+ .ui-date-picker__trigger--sm {
28
+ height: 28px;
29
+ padding: 0 var(--spacing-xs);
30
+ }
31
+
32
+ .ui-date-picker__trigger--lg {
33
+ height: 44px;
34
+ padding: 0 var(--spacing-md);
35
+ }
36
+
37
+ .ui-date-picker__trigger:hover:not(.is-disabled) {
38
+ border-color: var(--border-focus);
39
+ }
40
+
41
+ .ui-date-picker__trigger.is-focus {
42
+ border-color: var(--border-focus);
43
+ box-shadow: 0 0 0 3px var(--focus-ring);
44
+ }
45
+
46
+ .ui-date-picker__trigger:focus-visible {
47
+ outline: none;
48
+ border-color: var(--border-focus);
49
+ box-shadow: 0 0 0 3px var(--focus-ring);
50
+ }
51
+
52
+ .ui-date-picker__trigger.is-disabled {
53
+ background: var(--muted-bg);
54
+ color: var(--muted-fg);
55
+ cursor: not-allowed;
56
+ }
57
+
58
+ .ui-date-picker__icon {
59
+ display: inline-flex;
60
+ align-items: center;
61
+ color: var(--muted-fg);
62
+ flex-shrink: 0;
63
+ }
64
+
65
+ .ui-date-picker__text {
66
+ flex: 1;
67
+ min-width: 0;
68
+ overflow: hidden;
69
+ white-space: nowrap;
70
+ text-overflow: ellipsis;
71
+ }
72
+
73
+ .ui-date-picker__text.is-placeholder {
74
+ color: var(--muted-fg);
75
+ }
76
+
77
+ .ui-date-picker__clear {
78
+ display: inline-flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ flex-shrink: 0;
82
+ width: 18px;
83
+ height: 18px;
84
+ padding: 0;
85
+ border: 0;
86
+ border-radius: var(--rounded-full);
87
+ background: transparent;
88
+ color: var(--muted-fg);
89
+ cursor: pointer;
90
+ }
91
+
92
+ .ui-date-picker__clear:hover {
93
+ background: var(--accent-1);
94
+ color: var(--primary-fg);
95
+ }
@@ -0,0 +1,34 @@
1
+ // Configured Day.js singleton for the date-picker.
2
+ //
3
+ // Day.js ships as a tiny core; every feature the picker needs (custom format
4
+ // parsing, locale-aware week start, week/quarter numbers, inclusive comparisons)
5
+ // lives in an opt-in plugin. We register them ONCE here and re-export the same
6
+ // instance so every date-picker file shares one configured dayjs — importing
7
+ // `dayjs` directly elsewhere would get the unconfigured core.
8
+ //
9
+ // `dayjs.extend` is idempotent (re-extending with the same plugin is a no-op),
10
+ // so this module is safe to import from multiple files under both the Vite
11
+ // (Vue 3) and webpack (Vue 2) bundlers.
12
+ import dayjs from 'dayjs'
13
+
14
+ import customParseFormat from 'dayjs/plugin/customParseFormat'
15
+ import localeData from 'dayjs/plugin/localeData'
16
+ import weekday from 'dayjs/plugin/weekday'
17
+ import weekOfYear from 'dayjs/plugin/weekOfYear'
18
+ import isoWeek from 'dayjs/plugin/isoWeek'
19
+ import advancedFormat from 'dayjs/plugin/advancedFormat'
20
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
21
+ import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
22
+ import quarterOfYear from 'dayjs/plugin/quarterOfYear'
23
+
24
+ dayjs.extend(customParseFormat)
25
+ dayjs.extend(localeData)
26
+ dayjs.extend(weekday)
27
+ dayjs.extend(weekOfYear)
28
+ dayjs.extend(isoWeek)
29
+ dayjs.extend(advancedFormat)
30
+ dayjs.extend(isSameOrBefore)
31
+ dayjs.extend(isSameOrAfter)
32
+ dayjs.extend(quarterOfYear)
33
+
34
+ export default dayjs
@@ -0,0 +1,42 @@
1
+ .ui-cal-footer {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: space-between;
5
+ gap: var(--spacing-sm);
6
+ padding-top: var(--spacing-sm);
7
+ border-top: 1px solid var(--border-primary);
8
+ font-family: var(--font-family-body);
9
+ }
10
+
11
+ .ui-cal-footer__left {
12
+ display: inline-flex;
13
+ align-items: center;
14
+ }
15
+
16
+ .ui-cal-footer__right {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ gap: var(--spacing-xs);
20
+ }
21
+
22
+ .ui-cal-footer__link {
23
+ border: 0;
24
+ background: transparent;
25
+ cursor: pointer;
26
+ padding: 0;
27
+ font-family: inherit;
28
+ font-size: var(--paragraph-mini-font-size);
29
+ line-height: var(--paragraph-mini-line-height);
30
+ letter-spacing: var(--paragraph-mini-letter-spacing);
31
+ color: var(--primary-brand-fg);
32
+ }
33
+
34
+ .ui-cal-footer__link:hover:not(:disabled) {
35
+ color: var(--primary-brand-hover);
36
+ text-decoration: underline;
37
+ }
38
+
39
+ .ui-cal-footer__link:disabled {
40
+ color: var(--muted-fg);
41
+ cursor: not-allowed;
42
+ }