nitro-web 0.0.129 → 0.0.131
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/client/index.ts +1 -1
- package/components/auth/signin.tsx +1 -1
- package/components/partials/element/dropdown.tsx +11 -4
- package/components/partials/element/filters.tsx +5 -5
- package/components/partials/element/message.tsx +1 -1
- package/components/partials/element/modal.tsx +1 -1
- package/components/partials/form/field-date.tsx +6 -5
- package/components/partials/form/field-time.tsx +29 -11
- package/package.json +1 -1
- package/types/util.d.ts +19 -9
- package/types/util.d.ts.map +1 -1
- package/util.js +20 -10
package/client/index.ts
CHANGED
|
@@ -25,7 +25,7 @@ export { Accordion } from '../components/partials/element/accordion'
|
|
|
25
25
|
export { Avatar } from '../components/partials/element/avatar'
|
|
26
26
|
export { Button } from '../components/partials/element/button'
|
|
27
27
|
export { Calendar, type CalendarProps } from '../components/partials/element/calendar'
|
|
28
|
-
export { Dropdown } from '../components/partials/element/dropdown'
|
|
28
|
+
export { Dropdown, type DropdownProps } from '../components/partials/element/dropdown'
|
|
29
29
|
export { Filters, type FiltersHandleType, type FilterType } from '../components/partials/element/filters'
|
|
30
30
|
export { GithubLink } from '../components/partials/element/github-link'
|
|
31
31
|
export { Initials } from '../components/partials/element/initials'
|
|
@@ -25,7 +25,7 @@ export function Signin({ className, elements, redirectTo }: signinProps) {
|
|
|
25
25
|
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
// Autofill the email input from ?email=
|
|
28
|
-
const query = queryObject(location.search, true)
|
|
28
|
+
const query = queryObject(location.search, { emptyStringAsTrue: true })
|
|
29
29
|
if (query.email) setState({ ...state, email: query.email as string })
|
|
30
30
|
}, [location.search])
|
|
31
31
|
|
|
@@ -3,7 +3,7 @@ import { forwardRef, cloneElement } from 'react'
|
|
|
3
3
|
import { getSelectStyle, twMerge } from 'nitro-web'
|
|
4
4
|
import { CheckCircleIcon } from '@heroicons/react/24/solid'
|
|
5
5
|
|
|
6
|
-
type DropdownProps = {
|
|
6
|
+
export type DropdownProps = {
|
|
7
7
|
allowOverflow?: boolean
|
|
8
8
|
animate?: boolean
|
|
9
9
|
children?: React.ReactNode
|
|
@@ -34,6 +34,8 @@ type DropdownProps = {
|
|
|
34
34
|
minWidth?: number | string
|
|
35
35
|
maxHeight?: number | string
|
|
36
36
|
toggleCallback?: (isActive: boolean) => void
|
|
37
|
+
/** when keeping active when the children clicked **/
|
|
38
|
+
preventCloseOnClickChild?: boolean
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export const Dropdown = forwardRef(function Dropdown({
|
|
@@ -52,6 +54,7 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
52
54
|
minWidth,
|
|
53
55
|
maxHeight,
|
|
54
56
|
toggleCallback,
|
|
57
|
+
preventCloseOnClickChild,
|
|
55
58
|
}: DropdownProps, ref) {
|
|
56
59
|
// https://letsbuildui.dev/articles/building-a-dropdown-menu-component-with-react-hooks
|
|
57
60
|
isHoverable = isHoverable && !menuIsOpen
|
|
@@ -134,14 +137,18 @@ export const Dropdown = forwardRef(function Dropdown({
|
|
|
134
137
|
})
|
|
135
138
|
}, [isActive, dir])
|
|
136
139
|
|
|
137
|
-
function onMouseDown(e: { key: string, preventDefault: Function }) {
|
|
140
|
+
function onMouseDown(e: { key: string, preventDefault: Function, target: EventTarget | null }) {
|
|
138
141
|
if (e.key && e.key != 'Enter') return
|
|
139
142
|
if (e.key) e.preventDefault() // for button, stops buttons firing twice
|
|
140
|
-
|
|
143
|
+
|
|
144
|
+
if (!isHoverable && !menuIsOpen && ((menuToggles || e.key) || !isActive)) {
|
|
145
|
+
if (isActive && preventCloseOnClickChild && dropdownRef.current?.contains(e.target as Node)) return // keep active
|
|
146
|
+
setIsActive(!isActive)
|
|
147
|
+
}
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
function onClick(option: { onClick?: Function, preventCloseOnClick?: boolean }, e: React.MouseEvent) {
|
|
144
|
-
if (option.onClick) option.onClick(e)
|
|
151
|
+
if (option.onClick) option.onClick(e, option)
|
|
145
152
|
if (!menuIsOpen && !option?.preventCloseOnClick) setIsActive(!isActive)
|
|
146
153
|
}
|
|
147
154
|
|
|
@@ -43,8 +43,8 @@ const debounceTime = 250
|
|
|
43
43
|
|
|
44
44
|
export const Filters = forwardRef<FiltersHandleType, FiltersProps>(({
|
|
45
45
|
filters,
|
|
46
|
-
setState:
|
|
47
|
-
state:
|
|
46
|
+
setState: setStateProp,
|
|
47
|
+
state: stateProp,
|
|
48
48
|
buttonProps,
|
|
49
49
|
buttonCounterClassName,
|
|
50
50
|
buttonText,
|
|
@@ -56,8 +56,8 @@ export const Filters = forwardRef<FiltersHandleType, FiltersProps>(({
|
|
|
56
56
|
const navigate = useNavigate()
|
|
57
57
|
const [lastUpdated, setLastUpdated] = useState(0)
|
|
58
58
|
const [debouncedSubmit] = useState(() => debounce(submit, debounceTime))
|
|
59
|
-
const [
|
|
60
|
-
const [state, setState] = [
|
|
59
|
+
const [stateDefault, setStateDefault] = useState(() => ({ ...queryObject(location.search) }))
|
|
60
|
+
const [state, setState] = [stateProp || stateDefault, setStateProp || setStateDefault]
|
|
61
61
|
const stateRef = useRef(state)
|
|
62
62
|
const locationRef = useRef(location)
|
|
63
63
|
const count = useMemo(() => Object.keys(state).filter((k) => state[k] && filters?.some((f) => f.name === k)).length, [state, filters])
|
|
@@ -172,7 +172,7 @@ export const Filters = forwardRef<FiltersHandleType, FiltersProps>(({
|
|
|
172
172
|
}
|
|
173
173
|
{
|
|
174
174
|
filter.type !== 'select' &&
|
|
175
|
-
<Elements.Field
|
|
175
|
+
<Elements.Field
|
|
176
176
|
{...filter}
|
|
177
177
|
class="!mb-0"
|
|
178
178
|
// `filter.name` is a full path e.g. 'job.location', not just the key `location`
|
|
@@ -54,7 +54,7 @@ export function Message({ className, classNameWrapper, position='top-right' }: M
|
|
|
54
54
|
useEffect(() => {
|
|
55
55
|
// Finds a message in a query string and show it
|
|
56
56
|
let message
|
|
57
|
-
const query = queryObject(location.search, true)
|
|
57
|
+
const query = queryObject(location.search, { emptyStringAsTrue: true })
|
|
58
58
|
for (const key in query) {
|
|
59
59
|
if (!query.hasOwnProperty(key)) continue
|
|
60
60
|
for (const key2 in messageQueryMap) {
|
|
@@ -65,7 +65,7 @@ export function Modal({ show, setShow, children, maxWidth, minHeight, dismissabl
|
|
|
65
65
|
return (
|
|
66
66
|
<div
|
|
67
67
|
onClick={(e) => e.stopPropagation()}
|
|
68
|
-
class={`${twMerge(`fixed top-0 w-[100vw] h-[100vh] z-[
|
|
68
|
+
class={`${twMerge(`fixed top-0 w-[100vw] h-[100vh] z-[200] ${stateObj.root} ${rootClassName||''}`)} nitro-modal`}
|
|
69
69
|
>
|
|
70
70
|
<div class={`!absolute inset-0 box-content bg-gray-500/70 transition-opacity ${stateObj.bg}`}></div>
|
|
71
71
|
<div class={`relative h-[100vh] overflow-y-auto transition-[opacity,transform] ${stateObj.container}`}>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { format, isValid, parse } from 'date-fns'
|
|
3
3
|
import { getPrefixWidth } from 'nitro-web/util'
|
|
4
|
-
import { Calendar, Dropdown } from 'nitro-web'
|
|
4
|
+
import { Calendar, Dropdown, DropdownProps } from 'nitro-web'
|
|
5
5
|
import { DayPickerProps } from '../element/calendar'
|
|
6
6
|
import { TimePicker } from './field-time'
|
|
7
7
|
|
|
@@ -29,6 +29,8 @@ type PreFieldDateProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onCh
|
|
|
29
29
|
dir?: 'bottom-left'|'bottom-right'|'top-left'|'top-right'
|
|
30
30
|
/** Calendar props */
|
|
31
31
|
DayPickerProps?: DayPickerProps
|
|
32
|
+
/** Dropdown props */
|
|
33
|
+
DropdownProps?: DropdownProps
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
// An array is returned for mode = 'multiple' or 'range'
|
|
@@ -53,6 +55,7 @@ export function FieldDate({
|
|
|
53
55
|
showTime,
|
|
54
56
|
value: valueProp,
|
|
55
57
|
DayPickerProps,
|
|
58
|
+
DropdownProps,
|
|
56
59
|
...props
|
|
57
60
|
}: FieldDateProps) {
|
|
58
61
|
// Currently this displays the dates in local timezone and saves in utc. We should allow the user to display the dates in a
|
|
@@ -71,10 +74,7 @@ export function FieldDate({
|
|
|
71
74
|
|
|
72
75
|
// Convert the value to an array of valid* dates
|
|
73
76
|
const validDates = useMemo(() => {
|
|
74
|
-
const arrOfNumbers =
|
|
75
|
-
? value.split(/\s*,\s*/g).map(o => parseFloat(o))
|
|
76
|
-
: Array.isArray(value) ? value : [value]
|
|
77
|
-
|
|
77
|
+
const arrOfNumbers = Array.isArray(value) ? value : [value]
|
|
78
78
|
const out = arrOfNumbers.map((date) => {
|
|
79
79
|
if (typeof date === 'string' && !isNaN(parseFloat(date))) date = parseFloat(date)
|
|
80
80
|
return isValid(date) ? new Date(date as number) : null /// changed to null
|
|
@@ -162,6 +162,7 @@ export function FieldDate({
|
|
|
162
162
|
</div>
|
|
163
163
|
}
|
|
164
164
|
dir={dir}
|
|
165
|
+
{...DropdownProps}
|
|
165
166
|
>
|
|
166
167
|
<div className="grid grid-cols-1">
|
|
167
168
|
{Icon}
|
|
@@ -108,6 +108,11 @@ export function FieldTime({ onChange, value, Icon, dir = 'bottom-left', ...props
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
export function TimePicker({ date, onChange }: TimePickerProps) {
|
|
111
|
+
const refs = {
|
|
112
|
+
hour: useRef<HTMLDivElement>(null),
|
|
113
|
+
minute: useRef<HTMLDivElement>(null),
|
|
114
|
+
period: useRef<HTMLDivElement>(null),
|
|
115
|
+
}
|
|
111
116
|
const lists = [
|
|
112
117
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // hours
|
|
113
118
|
[
|
|
@@ -122,6 +127,13 @@ export function TimePicker({ date, onChange }: TimePickerProps) {
|
|
|
122
127
|
const hour = date ? parseInt(format(date, 'h')) : undefined
|
|
123
128
|
const minute = date ? parseInt(format(date, 'm')) : undefined
|
|
124
129
|
const period = date ? format(date, 'a') : undefined
|
|
130
|
+
|
|
131
|
+
// Scroll into view when the date changes
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (hour !== undefined) scrollIntoView('hour', hour)
|
|
134
|
+
if (minute !== undefined) scrollIntoView('minute', minute)
|
|
135
|
+
if (period) scrollIntoView('period', period)
|
|
136
|
+
}, [date])
|
|
125
137
|
|
|
126
138
|
const handleTimeChange = (type: 'hour' | 'minute' | 'period', value: string | number) => {
|
|
127
139
|
// Creates a new date object in the local timezone, and calls onChange with the timestamp
|
|
@@ -147,13 +159,18 @@ export function TimePicker({ date, onChange }: TimePickerProps) {
|
|
|
147
159
|
onChange(newDate.getTime())
|
|
148
160
|
}
|
|
149
161
|
|
|
150
|
-
function scrollIntoView(type: 'hour' | 'minute' | 'period', value: string | number
|
|
151
|
-
const container =
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
function scrollIntoView (type: 'hour' | 'minute' | 'period', value: string | number) {
|
|
163
|
+
const container = refs[type].current
|
|
164
|
+
if (!container) return
|
|
165
|
+
const element = container.querySelector(`[data-val="${value}"]`) as HTMLElement
|
|
166
|
+
if (!element) return
|
|
167
|
+
|
|
168
|
+
const target =
|
|
169
|
+
element.offsetTop
|
|
170
|
+
- (container.clientHeight / 2)
|
|
171
|
+
+ (element.clientHeight / 2)
|
|
172
|
+
|
|
173
|
+
container.scrollTo({ top: target, behavior: 'smooth' })
|
|
157
174
|
}
|
|
158
175
|
|
|
159
176
|
return (
|
|
@@ -164,17 +181,18 @@ export function TimePicker({ date, onChange }: TimePickerProps) {
|
|
|
164
181
|
return (
|
|
165
182
|
<div
|
|
166
183
|
key={i}
|
|
167
|
-
|
|
184
|
+
ref={refs[type]}
|
|
185
|
+
className="w-[60px] relative overflow-hidden hover:overflow-y-auto border-l border-gray-100 sm-scrollbar first:border-l-0"
|
|
168
186
|
>
|
|
169
|
-
<div className="w-[60px] absolute flex flex-col items-center">
|
|
187
|
+
<div className="w-[60px] absolute flex flex-col items-center py-2">
|
|
170
188
|
{/* using absolute since the scrollbar takes up space */}
|
|
171
189
|
{list.map(item => (
|
|
172
190
|
<div
|
|
173
191
|
className="py-[1px] flex group cursor-pointer"
|
|
192
|
+
data-val={item}
|
|
174
193
|
key={item}
|
|
175
|
-
onClick={(
|
|
194
|
+
onClick={(_e) => {
|
|
176
195
|
handleTimeChange(type, item)
|
|
177
|
-
scrollIntoView(type, item, e.currentTarget)
|
|
178
196
|
}}
|
|
179
197
|
>
|
|
180
198
|
<button
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.131",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
6
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|
package/types/util.d.ts
CHANGED
|
@@ -198,7 +198,7 @@ export function each(obj: {
|
|
|
198
198
|
} | [] | null, iteratee: Function, context?: object): object | [] | null;
|
|
199
199
|
/**
|
|
200
200
|
* Downloads a file
|
|
201
|
-
* @param {string|Blob|File} data
|
|
201
|
+
* @param {string|Blob|File|Uint8Array<ArrayBuffer>} data
|
|
202
202
|
* @param {string} filename
|
|
203
203
|
* @param {string} [mime]
|
|
204
204
|
* @param {string} [bom]
|
|
@@ -206,7 +206,7 @@ export function each(obj: {
|
|
|
206
206
|
*
|
|
207
207
|
* @link https://github.com/kennethjiang/js-file-download
|
|
208
208
|
*/
|
|
209
|
-
export function fileDownload(data: string | Blob | File
|
|
209
|
+
export function fileDownload(data: string | Blob | File | Uint8Array<ArrayBuffer>, filename: string, mime?: string, bom?: string): void;
|
|
210
210
|
/**
|
|
211
211
|
* Formats a string into a name
|
|
212
212
|
* @param {string} string
|
|
@@ -629,13 +629,20 @@ export function pick(obj: {
|
|
|
629
629
|
*
|
|
630
630
|
* Parses a query string into an object, or returns the last known matching cache
|
|
631
631
|
* @param {string} searchString - location.search e.g. '?page=1&book=my+%2B+book&date.0=1234567890'
|
|
632
|
-
* @param {
|
|
633
|
-
* @param {boolean} [
|
|
634
|
-
*
|
|
632
|
+
* @param {Object} [options] - options
|
|
633
|
+
* @param {boolean} [options.emptyStringAsTrue] - assign true to empty values
|
|
634
|
+
* @param {boolean} [options.splitCommaSeparated=true] - split comma-separated values into arrays
|
|
635
|
+
* @param {boolean} [options.groupArrayIndexes=true] - group splayed array indexes into real arrays,
|
|
636
|
+
* E.g. 'date.0'='1234567890' -> 'date' = ['1234567890']
|
|
635
637
|
* @returns {{[key: string]: string|true|(string|true)[]}} - e.g. { page: '1', book: 'my book', date: [1234567890] }
|
|
638
|
+
*
|
|
636
639
|
* todo: maybe add toDeepObject param? be kinda cool to have
|
|
637
640
|
*/
|
|
638
|
-
export function queryObject(searchString: string,
|
|
641
|
+
export function queryObject(searchString: string, options?: {
|
|
642
|
+
emptyStringAsTrue?: boolean;
|
|
643
|
+
splitCommaSeparated?: boolean;
|
|
644
|
+
groupArrayIndexes?: boolean;
|
|
645
|
+
}): {
|
|
639
646
|
[key: string]: string | true | (string | true)[];
|
|
640
647
|
};
|
|
641
648
|
/**
|
|
@@ -649,15 +656,18 @@ export function queryArray(searchString: string): object[];
|
|
|
649
656
|
* @param {{[key: string]: unknown}} obj - query object
|
|
650
657
|
* @param {string} [_path] - path to the object
|
|
651
658
|
* @param {{[key: string]: string}} [_output] - output object
|
|
652
|
-
* @param {
|
|
653
|
-
*
|
|
659
|
+
* @param {Object} [options] - options
|
|
660
|
+
* @param {boolean} [options.concatenateArrays=true] - will concatenate arrays into a comma-separated string, rather than separate keys,
|
|
661
|
+
* E.g. { date: [1,2] } -> 'date=1,2'
|
|
654
662
|
* @returns {string}
|
|
655
663
|
*/
|
|
656
664
|
export function queryString(obj: {
|
|
657
665
|
[key: string]: unknown;
|
|
658
666
|
}, _path?: string, _output?: {
|
|
659
667
|
[key: string]: string;
|
|
660
|
-
},
|
|
668
|
+
}, options?: {
|
|
669
|
+
concatenateArrays?: boolean;
|
|
670
|
+
}): string;
|
|
661
671
|
/**
|
|
662
672
|
* Axios request to the route
|
|
663
673
|
* @param {string} route - e.g. 'post /api/user'
|
package/types/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"AA2CA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BC;AAED;;;;;;;;;GASG;AACH,yBARa,sBAAsB,CAoBlC;AAED;;;;;GAKG;AACH,8BAJW,MAAM,cACN;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,GACrB,MAAM,CAKlB;AAED;;;;;;GAMG;AACH,+BALW,MAAM,oBACN,OAAO,gBACP,OAAO,GACL,MAAM,CAelB;AAED;;;;;GAKG;AACH,sCAJW,MAAM,wBACN,OAAO,GACL,MAAM,CAMlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,iCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;GAMG;AACH,gCALW,MAAM,aACN,MAAM,oBACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;GAIG;AACH,0CAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;;;;GAWG;AACH,4BAVW,MAAM,GAAC,IAAI,WACX,MAAM,aACN,MAAM,GACJ,MAAM,CAsBlB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,yBAnBuC,CAAC,SAA3B,CAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAI,QAI3B,CAAC,SACD,MAAM,YACN;IACN,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACS,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG;IACpD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,UAAU,CAAC,CAAC,CAAC,CAAA;CAC7B,CAwKH;AAED;;;;;GAKG;AACH,yBAJa,CAAC,OACH,CAAC,GACC,CAAC,CAgBb;AAED;;;;;GAKG;AACH,8BAJW,MAAM,GAAC,GAAG,EAAE,QACZ,MAAM,GACJ,OAAO,CAgBnB;AAED;;;;;;;GAOG;AACH,wBANa,CAAC,OACH,CAAC,QACD,MAAM,SACN,OAAO,WAAS,GACd,CAAC,CAKb;AAED;;;;;;;GAOG;AACH,gCANa,CAAC,QACH,CAAC,QACD,MAAM,SACN,OAAO,WAAS,GACd;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAgCpD;AAED;;;;;;GAMG;AACH,0BALW;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,GAAC,EAAE,GAAC,IAAI,gCAE5B,MAAM,GACJ,MAAM,GAAC,EAAE,GAAC,IAAI,CAmB1B;AAED;;;;;;;;;GASG;AACH,mCARW,MAAM,GAAC,IAAI,GAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"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"}
|
package/util.js
CHANGED
|
@@ -531,7 +531,7 @@ export function each (obj, iteratee, context) {
|
|
|
531
531
|
|
|
532
532
|
/**
|
|
533
533
|
* Downloads a file
|
|
534
|
-
* @param {string|Blob|File} data
|
|
534
|
+
* @param {string|Blob|File|Uint8Array<ArrayBuffer>} data
|
|
535
535
|
* @param {string} filename
|
|
536
536
|
* @param {string} [mime]
|
|
537
537
|
* @param {string} [bom]
|
|
@@ -1433,14 +1433,18 @@ export function pick (obj, keys) {
|
|
|
1433
1433
|
*
|
|
1434
1434
|
* Parses a query string into an object, or returns the last known matching cache
|
|
1435
1435
|
* @param {string} searchString - location.search e.g. '?page=1&book=my+%2B+book&date.0=1234567890'
|
|
1436
|
-
* @param {
|
|
1437
|
-
* @param {boolean} [
|
|
1438
|
-
*
|
|
1436
|
+
* @param {Object} [options] - options
|
|
1437
|
+
* @param {boolean} [options.emptyStringAsTrue] - assign true to empty values
|
|
1438
|
+
* @param {boolean} [options.splitCommaSeparated=true] - split comma-separated values into arrays
|
|
1439
|
+
* @param {boolean} [options.groupArrayIndexes=true] - group splayed array indexes into real arrays,
|
|
1440
|
+
* E.g. 'date.0'='1234567890' -> 'date' = ['1234567890']
|
|
1439
1441
|
* @returns {{[key: string]: string|true|(string|true)[]}} - e.g. { page: '1', book: 'my book', date: [1234567890] }
|
|
1442
|
+
*
|
|
1440
1443
|
* todo: maybe add toDeepObject param? be kinda cool to have
|
|
1441
1444
|
*/
|
|
1442
|
-
export function queryObject (searchString,
|
|
1445
|
+
export function queryObject (searchString, options={}) {
|
|
1443
1446
|
if (searchString.startsWith('?')) searchString = searchString.slice(1)
|
|
1447
|
+
const { emptyStringAsTrue = false, splitCommaSeparated = true, groupArrayIndexes = true } = options
|
|
1444
1448
|
const uniqueKey = searchString + (emptyStringAsTrue ? '-true' : '')
|
|
1445
1449
|
|
|
1446
1450
|
if (searchString === '') return {}
|
|
@@ -1459,8 +1463,12 @@ export function queryObject (searchString, emptyStringAsTrue, parseArrayItems=tr
|
|
|
1459
1463
|
if (emptyStringAsTrue) {
|
|
1460
1464
|
if (!flattened[key] && flattened[key] !== '0') result[key] = true
|
|
1461
1465
|
}
|
|
1466
|
+
// Split comma-separated values into arrays
|
|
1467
|
+
if (splitCommaSeparated && typeof flattened[key] === 'string' && flattened[key].includes(',')) {
|
|
1468
|
+
result[key] = flattened[key].split(',')
|
|
1469
|
+
}
|
|
1462
1470
|
// Convert splayed array items into a array objects, e.g. 'customer.0' = '1' -> 'customer' = ['1']
|
|
1463
|
-
if (
|
|
1471
|
+
if (groupArrayIndexes && key.match(/\.\d+$/)) {
|
|
1464
1472
|
const baseKey = key.replace(/\.\d+$/, '')
|
|
1465
1473
|
const index = Number(key.match(/\.(\d+)$/)?.[1] || '0')
|
|
1466
1474
|
if (Array.isArray(result[baseKey])) result[baseKey][index] = flattened[key]
|
|
@@ -1490,19 +1498,21 @@ export function queryArray (searchString) {
|
|
|
1490
1498
|
* @param {{[key: string]: unknown}} obj - query object
|
|
1491
1499
|
* @param {string} [_path] - path to the object
|
|
1492
1500
|
* @param {{[key: string]: string}} [_output] - output object
|
|
1493
|
-
* @param {
|
|
1494
|
-
*
|
|
1501
|
+
* @param {Object} [options] - options
|
|
1502
|
+
* @param {boolean} [options.concatenateArrays=true] - will concatenate arrays into a comma-separated string, rather than separate keys,
|
|
1503
|
+
* E.g. { date: [1,2] } -> 'date=1,2'
|
|
1495
1504
|
* @returns {string}
|
|
1496
1505
|
*/
|
|
1497
|
-
export function queryString (obj, _path='', _output,
|
|
1506
|
+
export function queryString (obj, _path='', _output, options={}) {
|
|
1498
1507
|
/** @type {{[key: string]: string}} */
|
|
1499
1508
|
const output = _output || {}
|
|
1509
|
+
const { concatenateArrays = true } = options
|
|
1500
1510
|
|
|
1501
1511
|
for (let key in obj) {
|
|
1502
1512
|
if (obj.hasOwnProperty(key)) {
|
|
1503
1513
|
if (typeof obj[key] == 'undefined' || obj[key] === '') continue
|
|
1504
1514
|
else if (concatenateArrays && Array.isArray(obj[key])) output[_path + key] = obj[key].join(',')
|
|
1505
|
-
else if (typeof obj[key] == 'object') queryString(/** @type {{[key: string]: unknown}} */(obj[key]), _path
|
|
1515
|
+
else if (typeof obj[key] == 'object') queryString(/** @type {{[key: string]: unknown}} */(obj[key]), _path+key+'.', output, options)
|
|
1506
1516
|
else output[_path + key] = obj[key] + ''
|
|
1507
1517
|
}
|
|
1508
1518
|
}
|