@campfire-interactive/inputs 0.1.1 → 0.2.2

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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as React from 'react';
2
2
 
3
3
  type DatePickerMode = 'date' | 'datetime' | 'time' | 'month' | 'quarter' | 'year';
4
4
  interface IDatePicker {
@@ -34,6 +34,6 @@ type DatePickerProps = IDatePicker;
34
34
  * is the `DatePickerProps` interface in `./types.ts` — nothing react-datepicker
35
35
  * specific leaks to consumers.
36
36
  */
37
- declare function DatePicker(props: DatePickerProps): react_jsx_runtime.JSX.Element;
37
+ declare function DatePicker(props: DatePickerProps): React.JSX.Element;
38
38
 
39
39
  export { DatePicker, type DatePickerMode, type DatePickerProps, type IDatePicker };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/DatePicker.tsx
2
+ import * as React from "react";
2
3
  import ReactDatePicker from "react-datepicker";
3
4
  import { format as fmt, parse as parseDate, isValid } from "date-fns";
4
5
  import "react-datepicker/dist/react-datepicker.css";
@@ -26,7 +27,7 @@ function styleInject(css, { insertAt } = {}) {
26
27
  }
27
28
 
28
29
  // src/DatePicker.css
29
- styleInject('.cfi-datepicker-wrapper {\n display: block;\n width: 100%;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container {\n display: block;\n width: 100%;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input {\n box-sizing: border-box;\n display: block;\n height: 2.25rem;\n width: 100%;\n padding: 0.25rem 2rem 0.25rem 0.75rem;\n border: 1px solid hsl(214.3 31.8% 91.4%);\n border-radius: 0.375rem;\n background-color: hsl(0 0% 100%);\n font-size: 0.875rem;\n line-height: 1.25rem;\n color: inherit;\n outline: none;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input::placeholder {\n color: hsl(215.4 16.3% 56.9%);\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input:focus,\n.cfi-datepicker-wrapper .react-datepicker__input-container input:focus-visible {\n border-color: hsl(222.2 47.4% 30%);\n box-shadow: 0 0 0 2px hsl(222.2 47.4% 30% / 0.15);\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input:disabled {\n background-color: hsl(210 40% 96.1%);\n color: hsl(215.4 16.3% 46.9%);\n cursor: not-allowed;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 1.25rem;\n width: 1.25rem;\n padding: 0;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon::after {\n content: "\\d7";\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 1.25rem;\n width: 1.25rem;\n padding: 0;\n background: transparent;\n border-radius: 0.25rem;\n color: hsl(215.4 16.3% 46.9%);\n font-size: 1.125rem;\n font-weight: 400;\n line-height: 1;\n transition: background-color 0.15s ease, color 0.15s ease;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon:hover::after {\n background-color: hsl(210 40% 94%);\n color: hsl(222.2 84% 4.9%);\n}\n');
30
+ styleInject('.cfi-datepicker-wrapper {\n display: block;\n width: 100%;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container {\n display: block;\n width: 100%;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input {\n box-sizing: border-box;\n display: block;\n height: 2.25rem;\n width: 100%;\n padding: 0.25rem 2rem 0.25rem 0.75rem;\n border: 1px solid var(--cfi-border, hsl(214.3 31.8% 91.4%));\n border-radius: 0.375rem;\n background-color: var(--cfi-surface, hsl(0 0% 100%));\n font-size: 0.875rem;\n line-height: 1.25rem;\n color: inherit;\n outline: none;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input::placeholder {\n color: var(--cfi-content-subtle, hsl(215.4 16.3% 56.9%));\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input:focus,\n.cfi-datepicker-wrapper .react-datepicker__input-container input:focus-visible {\n border-color: var(--cfi-border-focus, hsl(222.2 47.4% 30%));\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--cfi-border-focus, hsl(222.2 47.4% 30%)) 15%, transparent);\n}\n.cfi-datepicker-wrapper .react-datepicker__input-container input:disabled {\n background-color: var(--cfi-surface-disabled, hsl(210 40% 96.1%));\n color: var(--cfi-content-muted, hsl(215.4 16.3% 46.9%));\n cursor: not-allowed;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon {\n position: absolute;\n right: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 1.25rem;\n width: 1.25rem;\n padding: 0;\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon::after {\n content: "\\d7";\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 1.25rem;\n width: 1.25rem;\n padding: 0;\n background: transparent;\n border-radius: 0.25rem;\n color: var(--cfi-content-muted, hsl(215.4 16.3% 46.9%));\n font-size: 1.125rem;\n font-weight: 400;\n line-height: 1;\n transition: background-color 0.15s ease, color 0.15s ease;\n}\n.cfi-datepicker-wrapper .react-datepicker__close-icon:hover::after {\n background-color: var(--cfi-surface-hover, hsl(210 40% 94%));\n color: var(--cfi-content, hsl(222.2 84% 4.9%));\n}\n.cfi-datepicker-popper .react-datepicker {\n background-color: var(--cfi-surface-raised, #fff);\n border-color: var(--cfi-border, #aeaeae);\n color: var(--cfi-content, #000);\n}\n.cfi-datepicker-popper .react-datepicker__header {\n background-color: var(--cfi-surface-sunken, #f0f0f0);\n border-bottom-color: var(--cfi-border, #aeaeae);\n}\n.cfi-datepicker-popper .react-datepicker__current-month,\n.cfi-datepicker-popper .react-datepicker-time__header,\n.cfi-datepicker-popper .react-datepicker-year-header,\n.cfi-datepicker-popper .react-datepicker__day-name,\n.cfi-datepicker-popper .react-datepicker__day,\n.cfi-datepicker-popper .react-datepicker__time-name,\n.cfi-datepicker-popper .react-datepicker__month-text,\n.cfi-datepicker-popper .react-datepicker__quarter-text,\n.cfi-datepicker-popper .react-datepicker__year-text {\n color: var(--cfi-content, #000);\n}\n.cfi-datepicker-popper .react-datepicker__day:not([aria-disabled=true]):hover,\n.cfi-datepicker-popper .react-datepicker__month-text:hover,\n.cfi-datepicker-popper .react-datepicker__quarter-text:hover,\n.cfi-datepicker-popper .react-datepicker__year-text:hover,\n.cfi-datepicker-popper .react-datepicker__time-list-item:hover {\n background-color: var(--cfi-surface-hover, #f0f0f0) !important;\n}\n.cfi-datepicker-popper .react-datepicker__day--outside-month {\n color: var(--cfi-content-subtle, #000);\n}\n.cfi-datepicker-popper .react-datepicker__day--disabled,\n.cfi-datepicker-popper .react-datepicker__month-text--disabled,\n.cfi-datepicker-popper .react-datepicker__quarter-text--disabled,\n.cfi-datepicker-popper .react-datepicker__year-text--disabled,\n.cfi-datepicker-popper .react-datepicker__time-list-item--disabled {\n color: var(--cfi-content-disabled, #ccc) !important;\n}\n.cfi-datepicker-popper .react-datepicker__day--selected,\n.cfi-datepicker-popper .react-datepicker__day--in-range,\n.cfi-datepicker-popper .react-datepicker__day--keyboard-selected,\n.cfi-datepicker-popper .react-datepicker__month-text--selected,\n.cfi-datepicker-popper .react-datepicker__month-text--keyboard-selected,\n.cfi-datepicker-popper .react-datepicker__quarter-text--selected,\n.cfi-datepicker-popper .react-datepicker__quarter-text--keyboard-selected,\n.cfi-datepicker-popper .react-datepicker__year-text--selected,\n.cfi-datepicker-popper .react-datepicker__year-text--keyboard-selected,\n.cfi-datepicker-popper .react-datepicker__time-list-item--selected {\n background-color: var(--cfi-action, #216ba5) !important;\n color: var(--cfi-action-fg, #fff) !important;\n}\n.cfi-datepicker-popper .react-datepicker__time-container,\n.cfi-datepicker-popper .react-datepicker__time-container .react-datepicker__time {\n background-color: var(--cfi-surface-raised, #fff);\n border-color: var(--cfi-border, #aeaeae);\n}\n.cfi-datepicker-popper .react-datepicker__navigation-icon::before,\n.cfi-datepicker-popper .react-datepicker__year-read-view--down-arrow,\n.cfi-datepicker-popper .react-datepicker__month-read-view--down-arrow {\n border-color: var(--cfi-content-muted, #ccc);\n}\n.cfi-datepicker-popper .react-datepicker__triangle {\n fill: var(--cfi-surface-sunken, #f0f0f0);\n color: var(--cfi-surface-sunken, #f0f0f0);\n stroke: var(--cfi-border, #aeaeae);\n}\n');
30
31
 
31
32
  // src/DatePicker.tsx
32
33
  import { jsx } from "react/jsx-runtime";
@@ -45,6 +46,70 @@ var toDate = (value, formatStr) => {
45
46
  return isValid(d) ? d : null;
46
47
  };
47
48
  var toCanonicalString = (date, formatStr) => date && isValid(date) ? fmt(date, formatStr) : null;
49
+ var DATE_ALTS = [
50
+ "MM/dd/yyyy",
51
+ "M/d/yyyy",
52
+ "MM/dd/yy",
53
+ "M/d/yy",
54
+ "MM-dd-yyyy",
55
+ "M-d-yyyy",
56
+ "yyyy/MM/dd",
57
+ "yyyy-M-d",
58
+ "MMM d yyyy",
59
+ "MMM d, yyyy",
60
+ "MMMM d yyyy",
61
+ "MMMM d, yyyy"
62
+ ];
63
+ var TIME_ALTS = ["H:mm", "h:mm a", "h:mma", "h a", "ha", "HHmm"];
64
+ var TYPED_ALTERNATES = {
65
+ date: DATE_ALTS,
66
+ datetime: DATE_ALTS.flatMap((d) => TIME_ALTS.map((t) => `${d} ${t}`)),
67
+ time: TIME_ALTS,
68
+ month: [
69
+ "yyyy-M",
70
+ "yyyy/MM",
71
+ "yyyy/M",
72
+ "MM/yyyy",
73
+ "M/yyyy",
74
+ "MM-yyyy",
75
+ "M-yyyy",
76
+ "MM/yy",
77
+ "M/yy",
78
+ "MMM yyyy",
79
+ "MMMM yyyy",
80
+ "MMM yy"
81
+ ],
82
+ quarter: ["'Q'Q yyyy", "'Q'Q/yyyy", "'Q'Q-yyyy", "'Q'Qyyyy", "yyyy 'Q'Q", "yyyy-'Q'Q", "yyyy/'Q'Q"],
83
+ year: ["yyyy"]
84
+ };
85
+ var parseTyped = (text, formatStr, mode, ref = /* @__PURE__ */ new Date()) => {
86
+ let value = text.trim().replace(/\s+/g, " ");
87
+ if (!value) return null;
88
+ if (mode === "quarter") value = value.toUpperCase();
89
+ for (const f of [formatStr, ...TYPED_ALTERNATES[mode]]) {
90
+ const d = parseDate(value, f, ref);
91
+ if (!isValid(d)) continue;
92
+ if (/y/.test(f) && d.getFullYear() < 1e3) continue;
93
+ if (/yy/.test(f) && !/yyyy/.test(f) && fmt(d, f).toUpperCase() !== value.toUpperCase()) continue;
94
+ return d;
95
+ }
96
+ return null;
97
+ };
98
+ var grainKey = (x, mode) => {
99
+ switch (mode) {
100
+ case "year":
101
+ return x.getFullYear() * 1e4;
102
+ case "quarter":
103
+ return x.getFullYear() * 1e4 + Math.floor(x.getMonth() / 3) * 300;
104
+ case "month":
105
+ return x.getFullYear() * 1e4 + x.getMonth() * 100;
106
+ case "time":
107
+ return 0;
108
+ default:
109
+ return x.getFullYear() * 1e4 + x.getMonth() * 100 + x.getDate();
110
+ }
111
+ };
112
+ var outOfRange = (d, mode, min, max) => !!min && grainKey(d, mode) < grainKey(min, mode) || !!max && grainKey(d, mode) > grainKey(max, mode);
48
113
  function DatePicker(props) {
49
114
  const mode = props.mode ?? "date";
50
115
  const defaults = MODE_DEFAULTS[mode];
@@ -58,7 +123,24 @@ function DatePicker(props) {
58
123
  modeProps.timeIntervals = 15;
59
124
  }
60
125
  const selected = toDate(props.value ?? null, formatStr);
61
- const handleChange = (d) => props.onChange(toCanonicalString(d, formatStr));
126
+ const typed = React.useRef(null);
127
+ const handleChange = (d) => {
128
+ typed.current = null;
129
+ props.onChange(toCanonicalString(d, formatStr));
130
+ };
131
+ const handleChangeRaw = (event) => {
132
+ const target = event?.target;
133
+ typed.current = event?.type === "change" && target instanceof HTMLInputElement ? target.value : null;
134
+ };
135
+ const commitTyped = () => {
136
+ const text = typed.current;
137
+ typed.current = null;
138
+ if (text == null || !text.trim()) return;
139
+ const d = parseTyped(text, formatStr, mode, selected ?? /* @__PURE__ */ new Date());
140
+ if (!d || outOfRange(d, mode, props.minDate, props.maxDate)) return;
141
+ const next = toCanonicalString(d, formatStr);
142
+ if (next !== (props.value ?? null)) props.onChange(next);
143
+ };
62
144
  const Picker = ReactDatePicker;
63
145
  return /* @__PURE__ */ jsx(
64
146
  Picker,
@@ -66,6 +148,9 @@ function DatePicker(props) {
66
148
  id: props.id,
67
149
  selected: selected ?? void 0,
68
150
  onChange: handleChange,
151
+ onChangeRaw: handleChangeRaw,
152
+ onBlur: commitTyped,
153
+ onCalendarClose: commitTyped,
69
154
  placeholderText: placeholder,
70
155
  disabled: props.disabled,
71
156
  minDate: props.minDate,
package/package.json CHANGED
@@ -1,40 +1,40 @@
1
- {
2
- "name": "@campfire-interactive/inputs",
3
- "version": "0.1.1",
4
- "description": "Shared input components for Campfire Suite (date picker, etc.)",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
12
- }
13
- },
14
- "files": [
15
- "dist"
16
- ],
17
- "scripts": {
18
- "build": "tsup",
19
- "dev": "tsup --watch"
20
- },
21
- "peerDependencies": {
22
- "react": "^18.0.0 || ^19.0.0",
23
- "react-dom": "^18.0.0 || ^19.0.0"
24
- },
25
- "dependencies": {
26
- "date-fns": "^4.1.0",
27
- "react-datepicker": "^9.1.0"
28
- },
29
- "devDependencies": {
30
- "@types/react": "^19.0.0",
31
- "react": "^19.0.0",
32
- "react-dom": "^19.0.0",
33
- "tsup": "^8.0.0",
34
- "typescript": "^5.0.0"
35
- },
36
- "publishConfig": {
37
- "registry": "https://registry.npmjs.org",
38
- "access": "public"
39
- }
40
- }
1
+ {
2
+ "name": "@campfire-interactive/inputs",
3
+ "version": "0.2.2",
4
+ "description": "Shared input components for Campfire Suite (date picker, etc.)",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch"
20
+ },
21
+ "peerDependencies": {
22
+ "react": "^18.0.0 || ^19.0.0",
23
+ "react-dom": "^18.0.0 || ^19.0.0"
24
+ },
25
+ "dependencies": {
26
+ "date-fns": "^4.1.0",
27
+ "react-datepicker": "^9.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^19.0.0",
31
+ "react": "^19.0.0",
32
+ "react-dom": "^19.0.0",
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.0.0"
35
+ },
36
+ "publishConfig": {
37
+ "registry": "https://registry.npmjs.org",
38
+ "access": "public"
39
+ }
40
+ }