@koine/react 1.0.5 → 1.0.8
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/Alert/Alert.js +18 -0
- package/Alert/index.js +1 -0
- package/Animations/Reveal.js +17 -0
- package/Animations/Underline.js +15 -0
- package/Animations/index.js +3 -0
- package/Animations/useReveal.js +70 -0
- package/Autocomplete/AutocompleteDownshift.js +158 -0
- package/Autocomplete/AutocompleteDownshiftMultiselect.js +353 -0
- package/Autocomplete/AutocompleteMui.js +172 -0
- package/Autocomplete/AutocompleteReach.js +112 -0
- package/Autocomplete/components.js +89 -0
- package/Autocomplete/helpers.js +28 -0
- package/Autocomplete/index.js +3 -0
- package/Bg/BgColor.js +33 -0
- package/Bg/BgPhoto.js +59 -0
- package/Bg/BgSvg.js +15 -0
- package/Bg/index.js +3 -0
- package/Breadcrumbs/Breadcrumbs.js +70 -0
- package/Breadcrumbs/index.js +1 -0
- package/Buttons/Button.js +79 -0
- package/Buttons/ButtonComposite.d.ts +1 -1
- package/Buttons/ButtonComposite.js +53 -0
- package/Buttons/ButtonFab.js +8 -0
- package/Buttons/ButtonLink.js +16 -0
- package/Buttons/IconButton.js +19 -0
- package/Buttons/index.js +5 -0
- package/Calendar/CalendarDaygridCell.js +52 -0
- package/Calendar/CalendarDaygridNav.js +23 -0
- package/Calendar/CalendarDaygridTable.js +49 -0
- package/Calendar/CalendarLegend.js +12 -0
- package/Calendar/calendar-api-google.js +97 -0
- package/Calendar/index.js +6 -0
- package/Calendar/types.js +1 -0
- package/Calendar/useCalendar.js +166 -0
- package/Calendar/utils.js +197 -0
- package/Carousel/Carousel.js +378 -0
- package/Carousel/CarouselCss.js +39 -0
- package/Carousel/index.js +1 -0
- package/Collapsable/Collapsable.js +132 -0
- package/Collapsable/index.js +1 -0
- package/Debug/Debug.js +21 -0
- package/Debug/index.js +1 -0
- package/Dialog/Dialog.js +93 -0
- package/Dialog/index.js +1 -0
- package/Editor/Editor--tiptap.js +21 -0
- package/Editor/components.d.ts +1 -2
- package/Editor/components.js +28 -0
- package/Editor/index.js +1 -0
- package/Favicon/FaviconTags.js +14 -0
- package/Favicon/index.js +1 -0
- package/Forms/Checkbox/Checkbox.js +24 -0
- package/Forms/Checkbox/index.js +1 -0
- package/Forms/Feedback/Feedback.js +10 -0
- package/Forms/Feedback/index.js +1 -0
- package/Forms/Field/Field.js +61 -0
- package/Forms/Field/FieldControl.js +45 -0
- package/Forms/Field/FieldHint.js +6 -0
- package/Forms/Field/index.js +2 -0
- package/Forms/Form/Form.js +64 -0
- package/Forms/Form/index.js +1 -0
- package/Forms/Input/Input.js +25 -0
- package/Forms/Input/index.js +1 -0
- package/Forms/InputGroup/InputGroup.js +42 -0
- package/Forms/InputGroup/index.js +1 -0
- package/Forms/Label/Label.js +24 -0
- package/Forms/Label/index.js +1 -0
- package/Forms/Password/Password.js +32 -0
- package/Forms/Password/index.js +1 -0
- package/Forms/Radio/Radio.js +31 -0
- package/Forms/Radio/index.js +1 -0
- package/Forms/Switch/Switch.js +50 -0
- package/Forms/Switch/index.js +1 -0
- package/Forms/Textarea/Textarea.js +15 -0
- package/Forms/Textarea/TextareaRich.js +44 -0
- package/Forms/Textarea/index.js +2 -0
- package/Forms/Toggle/Toggle.js +79 -0
- package/Forms/Toggle/index.js +1 -0
- package/Forms/Toggle/useToggle.js +143 -0
- package/Forms/antispam.js +56 -0
- package/Forms/helpers.js +44 -0
- package/Forms/index.js +17 -0
- package/Forms/styles.js +60 -0
- package/Gauge/Gauge.js +102 -0
- package/Grid/Grid.js +79 -0
- package/Grid/index.js +1 -0
- package/Hamburger/Hamburger.js +55 -0
- package/Hamburger/index.js +1 -0
- package/Header/index.js +1 -0
- package/Header/useHeader.js +30 -0
- package/Hidden/Hidden.js +14 -0
- package/Hidden/index.js +1 -0
- package/Img/Img.js +34 -0
- package/Img/index.js +1 -0
- package/Link/Link.js +2 -0
- package/Link/LinkBlank.d.ts +1 -1
- package/Link/LinkBlank.js +28 -0
- package/Link/index.js +2 -0
- package/Menu/Menu.js +11 -0
- package/Menu/index.js +1 -0
- package/MenuItem/MenuItem.js +20 -0
- package/MenuItem/index.js +1 -0
- package/Meta/Meta.js +4 -0
- package/Meta/index.js +1 -0
- package/NoJs/NoJs.js +6 -0
- package/NoJs/index.js +1 -0
- package/Pagination/PaginationNav.js +87 -0
- package/Pagination/PaginationResults.js +10 -0
- package/Pagination/index.js +2 -0
- package/Pill/Pill.js +37 -0
- package/Pill/index.js +1 -0
- package/Progress/ProgressCircular.js +38 -0
- package/Progress/ProgressLinear.js +34 -0
- package/Progress/ProgressOverlay.js +40 -0
- package/Progress/index.js +3 -0
- package/Rating/Rating.js +93 -0
- package/Rating/index.js +45 -0
- package/Select/SelectDownshift.js +38 -0
- package/Select/components.js +20 -0
- package/Select/index.js +3 -0
- package/Sidebar/Sidebar.js +48 -0
- package/Sidebar/index.js +1 -0
- package/Spacing/Spacing.js +47 -0
- package/Spacing/index.js +1 -0
- package/Sticky/Sticky.js +220 -0
- package/Sticky/StickyCss.js +6 -0
- package/Sticky/index.js +1 -0
- package/Tabs/Tabs.js +67 -0
- package/Tabs/index.js +1 -0
- package/Typography/CopyPasteVisible.js +6 -0
- package/Typography/Native.js +47 -0
- package/Typography/ReadMore.js +71 -0
- package/Typography/TextLoop.js +45 -0
- package/Typography/TypeStairs.js +46 -0
- package/Typography/index.js +5 -0
- package/helpers/index.js +19 -0
- package/hooks/index.js +5 -0
- package/hooks/useDateLocale.js +30 -0
- package/hooks/useFocus.js +11 -0
- package/hooks/usePrevious.js +8 -0
- package/hooks/useTraceUpdate.js +20 -0
- package/hooks/useWindowSize.js +13 -0
- package/index.js +36 -0
- package/index.umd.js +232 -239
- package/package.json +15 -9
- package/styles/Body.js +17 -0
- package/styles/Global.js +50 -0
- package/styles/classed.js +11 -0
- package/styles/index.js +7 -0
- package/styles/media.js +150 -0
- package/styles/spacing.d.ts +6 -6
- package/styles/spacing.js +46 -0
- package/styles/styled.d.ts +2 -2
- package/styles/styled.js +27 -0
- package/styles/theme--vanilla.js +53 -0
- package/styles/theme.d.ts +0 -7
- package/styles/theme.js +38 -0
- package/types.js +1 -0
- package/typings.d.ts +21 -0
- package/index.esm.js +0 -9456
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { __awaiter, __rest } from "tslib";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
// forwardRef,
|
|
5
|
+
useCallback, useMemo, useState, } from "react";
|
|
6
|
+
import { useAutocomplete } from "@mui/base/AutocompleteUnstyled";
|
|
7
|
+
import { isString } from "@koine/utils";
|
|
8
|
+
import {
|
|
9
|
+
// triggerOnChange,
|
|
10
|
+
normaliseOptions, } from "../Forms/helpers";
|
|
11
|
+
import { normaliseAutocompleteValue } from "./helpers";
|
|
12
|
+
import { AutocompleteRoot, AutocompleteLabel, AutocompleteWrap, AutocompleteInner, AutocompleteItem, AutocompleteItemLabel, AutocompleteItemRemove,
|
|
13
|
+
// AutocompleteInputWrap,
|
|
14
|
+
AutocompleteInput, AutocompleteInputArrow, AutocompleteMenu, AutocompleteMenuItem, } from "./components";
|
|
15
|
+
import { InputProgress } from "../Forms/styles";
|
|
16
|
+
/**
|
|
17
|
+
* Autocomplete/autocomplete component based on [`@mui useAutocomplete hook`](https://mui.com/components/autocomplete/#useautocomplete).
|
|
18
|
+
*
|
|
19
|
+
* This component is design to work out of the box with [`react-hook-form`](https://react-hook-form.com/)
|
|
20
|
+
* and [`yup`](https://github.com/jquense/yup) alongside our custom `Field`
|
|
21
|
+
* component.
|
|
22
|
+
*
|
|
23
|
+
* After a lot of tests and attempts with `downshift` and `@reach` this proved
|
|
24
|
+
* the best headless hook, small in size and behaving correctly in all scenarios.
|
|
25
|
+
* `downshift` had in fact problems treating the initial `defaultValue` which
|
|
26
|
+
* here is elegantly managed by the `isOptionEqualToValue` option passed into
|
|
27
|
+
* the `useAutocomplete` hook.
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* Validation with `yup` and `react-hook-form` example:
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* const schema = object({
|
|
34
|
+
* // the value must be an array with at least one non-empty string
|
|
35
|
+
* test1: array(string().required()).required().min(1),
|
|
36
|
+
* // the value must be an array of strings or an empty array
|
|
37
|
+
* test2: array(string().required()).required(),
|
|
38
|
+
* }).required();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
// export const Autocomplete = <TOption, TValue>forwardRef<
|
|
42
|
+
// HTMLInputElement,
|
|
43
|
+
// PropsWithChildren<AutocompleteProps<TOption, TValue>
|
|
44
|
+
// >(function Autocomplete(
|
|
45
|
+
// {
|
|
46
|
+
// creatable,
|
|
47
|
+
// multiple,
|
|
48
|
+
// autoComplete,
|
|
49
|
+
// loadOptions,
|
|
50
|
+
// options: defaultOptions = [],
|
|
51
|
+
// defaultValue = [],
|
|
52
|
+
// label,
|
|
53
|
+
// register,
|
|
54
|
+
// setValue,
|
|
55
|
+
// // trigger,
|
|
56
|
+
// name,
|
|
57
|
+
// onChange,
|
|
58
|
+
// $ref,
|
|
59
|
+
// children,
|
|
60
|
+
// ...props
|
|
61
|
+
// },
|
|
62
|
+
// ref
|
|
63
|
+
// ) {
|
|
64
|
+
export const Autocomplete = (_a) => {
|
|
65
|
+
var { creatable, multiple, autoComplete, loadOptions, options: defaultOptions = [], defaultValue, value: controlledValue, defaultInputValue, label, placeholder, register, setValue,
|
|
66
|
+
// trigger,
|
|
67
|
+
name, onChange, $ref, children } = _a, props = __rest(_a, ["creatable", "multiple", "autoComplete", "loadOptions", "options", "defaultValue", "value", "defaultInputValue", "label", "placeholder", "register", "setValue", "name", "onChange", "$ref", "children"]);
|
|
68
|
+
const defaultOptionsMemo = useMemo(() => normaliseOptions(defaultOptions), [defaultOptions]);
|
|
69
|
+
const [options, setOptions] = useState(defaultOptionsMemo);
|
|
70
|
+
const [loading, setLoading] = useState(false);
|
|
71
|
+
const { getRootProps, getInputLabelProps, getInputProps, getTagProps, getListboxProps, getOptionProps, getPopupIndicatorProps, groupedOptions, value: stateValue, setAnchorEl, popupOpen, focused, } = useAutocomplete({
|
|
72
|
+
id: "Autocomplete",
|
|
73
|
+
multiple: multiple ? true : undefined,
|
|
74
|
+
freeSolo: creatable ? true : undefined,
|
|
75
|
+
// autoComplete: autoComplete ? true : undefined,
|
|
76
|
+
disableCloseOnSelect: true,
|
|
77
|
+
openOnFocus: true,
|
|
78
|
+
blurOnSelect: autoComplete && !multiple,
|
|
79
|
+
selectOnFocus: creatable,
|
|
80
|
+
// TODO: passing the defaultInputValue makes the input controlled, which is
|
|
81
|
+
// not what I want, so we probably need to handle the input default value
|
|
82
|
+
// ourselves
|
|
83
|
+
// inputValue: defaultInputValue,
|
|
84
|
+
// @ts-expect-error FIXME: how?
|
|
85
|
+
defaultValue,
|
|
86
|
+
// @ts-expect-error FIXME: how?
|
|
87
|
+
value: controlledValue,
|
|
88
|
+
// defaultValue: useMemo(
|
|
89
|
+
// () => normaliseAutocompleteValue(defaultValue, multiple),
|
|
90
|
+
// [defaultValue]
|
|
91
|
+
// ),
|
|
92
|
+
options: useMemo(() => (loadOptions ? options : defaultOptions), [loadOptions, options, defaultOptions]),
|
|
93
|
+
// update input change only if we are searching as you type, @see
|
|
94
|
+
// https://mui.com/components/autocomplete/#search-as-you-type
|
|
95
|
+
onInputChange: useCallback((_event, inputValue) => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
if (!loadOptions) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (inputValue) {
|
|
100
|
+
setLoading(true);
|
|
101
|
+
try {
|
|
102
|
+
const newOptions = yield loadOptions(inputValue);
|
|
103
|
+
setOptions(newOptions);
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
console.warn(e);
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
setLoading(false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
setOptions(options);
|
|
114
|
+
// TODO: clear like behaviour?
|
|
115
|
+
// triggerChange({ value: "", label: "" });
|
|
116
|
+
}
|
|
117
|
+
}), [loadOptions, options]),
|
|
118
|
+
// TODO: check if we need this, probably, and check how to structure the
|
|
119
|
+
// callback, here we get the actual input event
|
|
120
|
+
onChange: (event, newValue) => {
|
|
121
|
+
const value = normaliseAutocompleteValue(newValue, multiple);
|
|
122
|
+
// @ts-expect-error FIXME: how?
|
|
123
|
+
if (onChange)
|
|
124
|
+
onChange(newValue);
|
|
125
|
+
if (setValue)
|
|
126
|
+
setValue(name, value, { shouldValidate: true });
|
|
127
|
+
// triggerOnChange(onChange, name, value);
|
|
128
|
+
},
|
|
129
|
+
// support both freeSolo free text and full option structure
|
|
130
|
+
isOptionEqualToValue: (option, value) => {
|
|
131
|
+
const optValue = isString(option) ? option : option.value;
|
|
132
|
+
const valValue = isString(value) ? value : value.value;
|
|
133
|
+
return optValue === valValue;
|
|
134
|
+
},
|
|
135
|
+
getOptionLabel: (option) => {
|
|
136
|
+
// @ts-expect-error TODO: I don't get this error
|
|
137
|
+
return isString(option) ? option : option.label || "";
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
const value = typeof controlledValue !== "undefined" ? controlledValue : stateValue;
|
|
141
|
+
const inputProps = () => {
|
|
142
|
+
const autocompleteProps = getInputProps();
|
|
143
|
+
// here we merge the mui's `useAutocomplete` props with the react-hook-form's
|
|
144
|
+
// `register` props
|
|
145
|
+
const registerProps = register
|
|
146
|
+
? register(name, {
|
|
147
|
+
// @ts-expect-error FIXME: can't remember
|
|
148
|
+
ref: autocompleteProps.ref.current,
|
|
149
|
+
// this makes the validation works when a valid `defaultValue`
|
|
150
|
+
// is provided
|
|
151
|
+
value: normaliseAutocompleteValue(value, multiple),
|
|
152
|
+
})
|
|
153
|
+
: {};
|
|
154
|
+
return Object.assign(Object.assign({}, registerProps), autocompleteProps);
|
|
155
|
+
};
|
|
156
|
+
// to focus the input on error this works too
|
|
157
|
+
// @see https://react-hook-form.com/faqs#question12 but probably it is
|
|
158
|
+
// better to do as now passing the input ref to the register options
|
|
159
|
+
// useEffect(() => {
|
|
160
|
+
// if (errors[name]) {
|
|
161
|
+
// inputProps.ref.current.focus();
|
|
162
|
+
// }
|
|
163
|
+
// }, [errors, name, inputProps.ref]);
|
|
164
|
+
return (_jsxs(AutocompleteRoot, { children: [label && (_jsx(AutocompleteLabel, Object.assign({}, getInputLabelProps(), { children: label }))), _jsxs(AutocompleteWrap, Object.assign({}, getRootProps(), { "data-focus": focused }, { children: [_jsxs(AutocompleteInner, Object.assign({ ref: setAnchorEl }, { children: [multiple &&
|
|
165
|
+
value.map((valueItem, index) => {
|
|
166
|
+
const _a = getTagProps({ index }), { onDelete, key } = _a, tagProps = __rest(_a, ["onDelete", "key"]);
|
|
167
|
+
return (_jsxs(AutocompleteItem, Object.assign({}, tagProps, { children: [_jsx(AutocompleteItemLabel, { children: isString(valueItem)
|
|
168
|
+
? valueItem
|
|
169
|
+
: valueItem.Label || valueItem.label }), _jsx(AutocompleteItemRemove, Object.assign({ onClick: onDelete }, { children: "\u2715" }))] }), key));
|
|
170
|
+
}), _jsx(AutocompleteInput, Object.assign({}, inputProps(), { placeholder: placeholder }))] })), !!options.length && (_jsx(AutocompleteInputArrow, Object.assign({}, getPopupIndicatorProps(), { isOpen: popupOpen }))), loading && _jsx(InputProgress, {})] })), groupedOptions.length ? (_jsx(AutocompleteMenu, Object.assign({}, getListboxProps(), { children: groupedOptions.map((option, index) => (_jsx(AutocompleteMenuItem, Object.assign({}, getOptionProps({ option, index }), { children: isString(option) ? option : option.Label || option.label }), index))) }))) : null, children] }));
|
|
171
|
+
// });
|
|
172
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// TODO: remove, just use mui version...
|
|
2
|
+
export const Autocomplete = null;
|
|
3
|
+
// import {
|
|
4
|
+
// forwardRef,
|
|
5
|
+
// useCallback,
|
|
6
|
+
// useState,
|
|
7
|
+
// ForwardedRef,
|
|
8
|
+
// ReactNode,
|
|
9
|
+
// ComponentPropsWithRef,
|
|
10
|
+
// CSSProperties,
|
|
11
|
+
// ChangeEventHandler,
|
|
12
|
+
// } from "react";
|
|
13
|
+
// import {
|
|
14
|
+
// Combobox,
|
|
15
|
+
// ComboboxInput,
|
|
16
|
+
// ComboboxPopover,
|
|
17
|
+
// ComboboxList,
|
|
18
|
+
// ComboboxOption,
|
|
19
|
+
// ComboboxOptionText,
|
|
20
|
+
// } from "@reach/combobox";
|
|
21
|
+
// import {
|
|
22
|
+
// AutocompleteRoot,
|
|
23
|
+
// AutocompleteInput,
|
|
24
|
+
// AutocompleteLabel,
|
|
25
|
+
// } from "./components";
|
|
26
|
+
// import type { Option } from "../types";
|
|
27
|
+
// import { SetRequired } from "@koine/utils";
|
|
28
|
+
// export type AutocompleteOption =
|
|
29
|
+
// | null
|
|
30
|
+
// | (Option & {
|
|
31
|
+
// key: string;
|
|
32
|
+
// });
|
|
33
|
+
// export type AutocompleteProps = SetRequired<
|
|
34
|
+
// ComponentPropsWithRef<"input">,
|
|
35
|
+
// "onChange" | "name"
|
|
36
|
+
// > & {
|
|
37
|
+
// onSelect?: (option?: AutocompleteOption) => any;
|
|
38
|
+
// options: AutocompleteOption[];
|
|
39
|
+
// loadOptions: (query?: string) => Promise<AutocompleteOption[]>;
|
|
40
|
+
// label?: string | ReactNode;
|
|
41
|
+
// className?: string;
|
|
42
|
+
// style?: CSSProperties;
|
|
43
|
+
// $ref: ForwardedRef<HTMLInputElement>;
|
|
44
|
+
// };
|
|
45
|
+
// export const Autocomplete = forwardRef<HTMLInputElement, AutocompleteProps>(
|
|
46
|
+
// function Autocomplete(
|
|
47
|
+
// {
|
|
48
|
+
// options = [],
|
|
49
|
+
// label,
|
|
50
|
+
// name,
|
|
51
|
+
// value,
|
|
52
|
+
// onChange,
|
|
53
|
+
// loadOptions,
|
|
54
|
+
// $ref,
|
|
55
|
+
// className,
|
|
56
|
+
// style,
|
|
57
|
+
// ...props
|
|
58
|
+
// },
|
|
59
|
+
// ref
|
|
60
|
+
// ) {
|
|
61
|
+
// const [items, setItems] = useState(options);
|
|
62
|
+
// const [loading, setLoading] = useState(false);
|
|
63
|
+
// const handleInputValueChange: ChangeEventHandler<HTMLInputElement> =
|
|
64
|
+
// useCallback(
|
|
65
|
+
// async (event) => {
|
|
66
|
+
// const inputValue = event.target.value;
|
|
67
|
+
// if (loadOptions) {
|
|
68
|
+
// setLoading(true);
|
|
69
|
+
// try {
|
|
70
|
+
// const newOptions = await loadOptions(inputValue);
|
|
71
|
+
// setItems(newOptions);
|
|
72
|
+
// } catch (e) {}
|
|
73
|
+
// setLoading(false);
|
|
74
|
+
// }
|
|
75
|
+
// },
|
|
76
|
+
// [loadOptions]
|
|
77
|
+
// );
|
|
78
|
+
// return (
|
|
79
|
+
// <AutocompleteRoot>
|
|
80
|
+
// {label && <AutocompleteLabel>{label}</AutocompleteLabel>}
|
|
81
|
+
// <Combobox aria-label="choose a fruit" openOnFocus={true}>
|
|
82
|
+
// <AutocompleteInput
|
|
83
|
+
// forwardedAs={ComboboxInput}
|
|
84
|
+
// ref={$ref}
|
|
85
|
+
// onChange={handleInputValueChange}
|
|
86
|
+
// selectOnClick={true}
|
|
87
|
+
// autocomplete={false}
|
|
88
|
+
// />
|
|
89
|
+
// {(!!items.length || loading) && (
|
|
90
|
+
// <ComboboxPopover>
|
|
91
|
+
// <ComboboxList persistSelection>
|
|
92
|
+
// {items
|
|
93
|
+
// // .filter(item => !inputValue || item.includes(inputValue))
|
|
94
|
+
// .map(
|
|
95
|
+
// (item, index) =>
|
|
96
|
+
// item && (
|
|
97
|
+
// <ComboboxOption
|
|
98
|
+
// key={`${item.value}${index}`}
|
|
99
|
+
// value={item.label}
|
|
100
|
+
// >
|
|
101
|
+
// <ComboboxOptionText />
|
|
102
|
+
// </ComboboxOption>
|
|
103
|
+
// )
|
|
104
|
+
// )}
|
|
105
|
+
// </ComboboxList>
|
|
106
|
+
// </ComboboxPopover>
|
|
107
|
+
// )}
|
|
108
|
+
// </Combobox>
|
|
109
|
+
// </AutocompleteRoot>
|
|
110
|
+
// );
|
|
111
|
+
// }
|
|
112
|
+
// );
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { Label } from "../Forms/Label/Label";
|
|
3
|
+
import { InputWrap, InputMain } from "../Forms/Input/Input";
|
|
4
|
+
import { SelectArrow } from "../Select/components";
|
|
5
|
+
import { Menu } from "../Menu/Menu";
|
|
6
|
+
import { MenuItem } from "../MenuItem/MenuItem";
|
|
7
|
+
import { btnStyleReset } from "../Buttons";
|
|
8
|
+
import { inputReset } from "../Forms/styles";
|
|
9
|
+
import { ellipsis } from "../styles/styled";
|
|
10
|
+
const AUTOCOMPLETE_ITEM_GUTTER = 3;
|
|
11
|
+
/**
|
|
12
|
+
* Space between one selected item and the other
|
|
13
|
+
*/
|
|
14
|
+
const AUTOCOMPLETE_ITEM_SPACER = 6;
|
|
15
|
+
const AUTOCOMPLETE_ITEM_REMOVE_WIDTH = 20;
|
|
16
|
+
export const AutocompleteRoot = styled.div `
|
|
17
|
+
position: relative;
|
|
18
|
+
`;
|
|
19
|
+
export const AutocompleteLabel = styled(Label) ``;
|
|
20
|
+
export const AutocompleteWrap = styled(InputWrap) `
|
|
21
|
+
${inputReset}
|
|
22
|
+
`;
|
|
23
|
+
export const AutocompleteInner = styled(InputMain) `
|
|
24
|
+
display: inline-flex;
|
|
25
|
+
flex-wrap: wrap;
|
|
26
|
+
margin: -${AUTOCOMPLETE_ITEM_SPACER}px;
|
|
27
|
+
margin-right: 0;
|
|
28
|
+
`;
|
|
29
|
+
export const AutocompleteItem = styled.span `
|
|
30
|
+
position: relative;
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
margin: ${AUTOCOMPLETE_ITEM_GUTTER}px;
|
|
33
|
+
max-width: calc(100% - 6px);
|
|
34
|
+
user-select: none;
|
|
35
|
+
align-items: center;
|
|
36
|
+
padding: 0 ${AUTOCOMPLETE_ITEM_REMOVE_WIDTH}px 0 ${AUTOCOMPLETE_ITEM_GUTTER}px;
|
|
37
|
+
font-size: 80%;
|
|
38
|
+
background: var(--accent400);
|
|
39
|
+
|
|
40
|
+
&:hover {
|
|
41
|
+
background: var(--accent300);
|
|
42
|
+
color: white;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&:focus {
|
|
46
|
+
outline: 0px;
|
|
47
|
+
background: var(--grey700);
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
export const AutocompleteItemLabel = styled.span `
|
|
51
|
+
padding: 0 ${AUTOCOMPLETE_ITEM_GUTTER}px;
|
|
52
|
+
${ellipsis}
|
|
53
|
+
`;
|
|
54
|
+
export const AutocompleteItemRemove = styled.span `
|
|
55
|
+
${btnStyleReset}
|
|
56
|
+
position: absolute;
|
|
57
|
+
top: 0;
|
|
58
|
+
right: 0;
|
|
59
|
+
width: ${AUTOCOMPLETE_ITEM_REMOVE_WIDTH}px;
|
|
60
|
+
border: 0;
|
|
61
|
+
height: 100%;
|
|
62
|
+
color: inherit;
|
|
63
|
+
line-height: 1;
|
|
64
|
+
`;
|
|
65
|
+
export const AutocompleteInputWrap = styled.div `
|
|
66
|
+
display: flex;
|
|
67
|
+
flex: 1;
|
|
68
|
+
`;
|
|
69
|
+
export const AutocompleteInput = styled.input `
|
|
70
|
+
flex-grow: 1;
|
|
71
|
+
width: 0;
|
|
72
|
+
min-width: 30px;
|
|
73
|
+
border: 0;
|
|
74
|
+
padding: 0 ${AUTOCOMPLETE_ITEM_SPACER}px;
|
|
75
|
+
text-overflow: ellipsis;
|
|
76
|
+
background: transparent;
|
|
77
|
+
|
|
78
|
+
&:focus {
|
|
79
|
+
outline: none;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
/**
|
|
83
|
+
* This cannot be a button otherwise on `Enter` the form would submit instead
|
|
84
|
+
* of opening the dropdown or adding the selection. There are too many events
|
|
85
|
+
* to prevent if we were using a standard HTML `<button>`
|
|
86
|
+
*/
|
|
87
|
+
export const AutocompleteInputArrow = styled(SelectArrow) ``;
|
|
88
|
+
export const AutocompleteMenu = styled(Menu) ``;
|
|
89
|
+
export const AutocompleteMenuItem = styled(MenuItem) ``;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { isString, isArray } from "@koine/utils";
|
|
2
|
+
// export function normaliseAutocompleteValue(
|
|
3
|
+
// value?: AutocompleteValue,
|
|
4
|
+
// asArray?: true
|
|
5
|
+
// ): string[];
|
|
6
|
+
// export function normaliseAutocompleteValue(
|
|
7
|
+
// value?: AutocompleteValue,
|
|
8
|
+
// asArray?: false
|
|
9
|
+
// ): string;
|
|
10
|
+
// export function normaliseAutocompleteValue(
|
|
11
|
+
// value?: AutocompleteValue,
|
|
12
|
+
// asArray?: undefined
|
|
13
|
+
// ): string;
|
|
14
|
+
export function normaliseAutocompleteValue(value, asArray) {
|
|
15
|
+
if (!value) {
|
|
16
|
+
return asArray ? [""] : "";
|
|
17
|
+
}
|
|
18
|
+
if (isString(value)) {
|
|
19
|
+
return asArray ? [value] : value;
|
|
20
|
+
}
|
|
21
|
+
if (isArray(value)) {
|
|
22
|
+
const values = value.map((valueItem) => {
|
|
23
|
+
return isString(valueItem) ? valueItem : valueItem.value;
|
|
24
|
+
});
|
|
25
|
+
return asArray ? values : values.join(",");
|
|
26
|
+
}
|
|
27
|
+
return asArray ? [value.value] : value.value;
|
|
28
|
+
}
|
package/Bg/BgColor.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { overlay } from "../styles";
|
|
5
|
+
import { Container } from "../Grid";
|
|
6
|
+
export const BgColor = styled.div `
|
|
7
|
+
background: ${(p) => p.$bg};
|
|
8
|
+
`;
|
|
9
|
+
export const BgColorSkewed = styled.div `
|
|
10
|
+
position: relative;
|
|
11
|
+
/* overflow: hidden; */
|
|
12
|
+
|
|
13
|
+
&:before {
|
|
14
|
+
z-index: -1;
|
|
15
|
+
content: "";
|
|
16
|
+
${(p) => `
|
|
17
|
+
${overlay}
|
|
18
|
+
transform: ${p.$transform};
|
|
19
|
+
background: ${p.$bg};
|
|
20
|
+
`}
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
export const BgContainer = (_a) => {
|
|
24
|
+
var { color, skewY = 0, rotate = 0, scaleY = 1, // 0.85,
|
|
25
|
+
scaleX = 1, // 4,
|
|
26
|
+
perspective = 0 } = _a, //100,
|
|
27
|
+
containerProps = __rest(_a, ["color", "skewY", "rotate", "scaleY", "scaleX", "perspective"]);
|
|
28
|
+
let $transform = "";
|
|
29
|
+
if (skewY || rotate) {
|
|
30
|
+
$transform = `perspective(${perspective}vw) rotateY(${rotate}deg) skewY(${skewY}deg) scaleY(${scaleY}) scaleX(${scaleX})`;
|
|
31
|
+
}
|
|
32
|
+
return $transform ? (_jsx(BgColorSkewed, Object.assign({ "$bg": color, "$transform": $transform }, { children: _jsx(Container, Object.assign({ style: { position: "relative" } }, containerProps)) }))) : (_jsx(BgColor, Object.assign({ "$bg": color }, { children: _jsx(Container, Object.assign({}, containerProps)) })));
|
|
33
|
+
};
|
package/Bg/BgPhoto.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import { Container } from "../Grid";
|
|
4
|
+
import { Hidden } from "../Hidden";
|
|
5
|
+
const BgPhotoWrap = styled(Hidden) `
|
|
6
|
+
z-index: -10;
|
|
7
|
+
position: fixed;
|
|
8
|
+
top: 0;
|
|
9
|
+
right: 0;
|
|
10
|
+
bottom: 0;
|
|
11
|
+
left: 0;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
background-repeat: no-repeat;
|
|
15
|
+
background-position: top left;
|
|
16
|
+
background-size: contain;
|
|
17
|
+
filter: hue-rotate(-36deg);
|
|
18
|
+
opacity: 0.8;
|
|
19
|
+
`;
|
|
20
|
+
const BgPhotoMask = styled(Container) `
|
|
21
|
+
position: relative;
|
|
22
|
+
min-height: 100%;
|
|
23
|
+
|
|
24
|
+
&:before {
|
|
25
|
+
content: "";
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 0;
|
|
28
|
+
height: 100%;
|
|
29
|
+
right: calc(100% - ${(p) => p.$overlap + 2}px);
|
|
30
|
+
width: ${(p) => {
|
|
31
|
+
const containerSizePx = p.theme.breakpoints[p.containerSize];
|
|
32
|
+
return `calc(((100vw - ${containerSizePx}px) / 2) + ${p.$overlap + 2}px)`;
|
|
33
|
+
}};
|
|
34
|
+
background: linear-gradient(
|
|
35
|
+
90deg,
|
|
36
|
+
rgba(var(--bodyBg-rgb, 0)) 0%,
|
|
37
|
+
rgba(var(--bodyBg-rgb, 1)) 100%
|
|
38
|
+
),
|
|
39
|
+
linear-gradient(
|
|
40
|
+
60deg,
|
|
41
|
+
rgba(var(--bodyBg-rgb, 0)) 0%,
|
|
42
|
+
rgba(var(--bodyBg-rgb, 1)) 70%
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&:after {
|
|
47
|
+
content: "";
|
|
48
|
+
position: absolute;
|
|
49
|
+
top: 0;
|
|
50
|
+
height: 100%;
|
|
51
|
+
left: ${(p) => p.$overlap + 1}px;
|
|
52
|
+
width: 100vw;
|
|
53
|
+
background: var(--bodyBg);
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
export const BgPhoto = ({ src, containerSize = "xl", $overlap = 0, }) => {
|
|
57
|
+
const styledProps = { containerSize, $overlap };
|
|
58
|
+
return (_jsx(BgPhotoWrap, Object.assign({ style: { backgroundImage: `url(${src})` }, "$max": "xxl" }, { children: _jsx(BgPhotoMask, Object.assign({ size: containerSize }, styledProps)) })));
|
|
59
|
+
};
|
package/Bg/BgSvg.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
const Root = styled.svg `
|
|
4
|
+
position: fixed;
|
|
5
|
+
z-index: -2;
|
|
6
|
+
bottom: 0;
|
|
7
|
+
transform: rotate(180deg);
|
|
8
|
+
opacity: 0.9;
|
|
9
|
+
`;
|
|
10
|
+
/**
|
|
11
|
+
* Centered triangle shape
|
|
12
|
+
*/
|
|
13
|
+
export const BgSvg = ({ color }) => {
|
|
14
|
+
return (_jsx(Root, Object.assign({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 1200 120", preserveAspectRatio: "none" }, { children: _jsx("path", { d: "M1200 0L0 0 598.97 114.72 1200 0z", fill: color }) })));
|
|
15
|
+
};
|
package/Bg/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import styled, { css } from "styled-components";
|
|
4
|
+
import { m } from "framer-motion";
|
|
5
|
+
import { MdKeyboardArrowRight as IconDelimiter } from "react-icons/md";
|
|
6
|
+
import { titleCase } from "@koine/utils";
|
|
7
|
+
import { max, min } from "../styles/media";
|
|
8
|
+
const LINK_GUTTER_X = 10;
|
|
9
|
+
const Root = styled.nav `
|
|
10
|
+
display: flex;
|
|
11
|
+
position: relative;
|
|
12
|
+
`;
|
|
13
|
+
const Inner = styled.div `
|
|
14
|
+
display: flex;
|
|
15
|
+
font-size: 11px;
|
|
16
|
+
color: var(--grey100);
|
|
17
|
+
${min.sm} {
|
|
18
|
+
font-size: 12px;
|
|
19
|
+
}
|
|
20
|
+
${max.lg} {
|
|
21
|
+
max-width: 100%;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
const Item = styled(m.div) `
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
/* margin: 0 10px 0 0; */
|
|
30
|
+
|
|
31
|
+
&:first-child {
|
|
32
|
+
margin-left: -${LINK_GUTTER_X / 2}px;
|
|
33
|
+
}
|
|
34
|
+
${min.sm} {
|
|
35
|
+
&:first-child {
|
|
36
|
+
margin-left: -${LINK_GUTTER_X}px;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
const itemChild = css `
|
|
41
|
+
display: block;
|
|
42
|
+
padding: 10px ${LINK_GUTTER_X / 2}px;
|
|
43
|
+
|
|
44
|
+
${min.sm} {
|
|
45
|
+
padding: 10px ${LINK_GUTTER_X}px;
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
const ItemLink = styled.a `
|
|
49
|
+
${itemChild}
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
&:hover {
|
|
52
|
+
text-decoration: underline;
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
const ItemCurrent = styled.span `
|
|
56
|
+
${itemChild}
|
|
57
|
+
`;
|
|
58
|
+
const ItemSeparator = styled(IconDelimiter) ``;
|
|
59
|
+
export const KoineBreadcrumbs = (_a) => {
|
|
60
|
+
var { items = [], Koine } = _a, props = __rest(_a, ["items", "Koine"]);
|
|
61
|
+
if (!items.length) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const { Link } = Koine;
|
|
65
|
+
return (_jsx(Root, Object.assign({}, props, { children: _jsx(Inner, { children: items.map((item, idx) => (_jsxs(Item, Object.assign({ initial: { opacity: 0, x: 20 }, animate: {
|
|
66
|
+
opacity: 1,
|
|
67
|
+
x: 0,
|
|
68
|
+
transition: { delay: idx * 0.2 },
|
|
69
|
+
} }, { children: [item.url && (_jsx(ItemLink, Object.assign({ as: Link, href: item.url }, { children: titleCase(item.title) }))), !item.url && _jsx(ItemCurrent, { children: titleCase(item.title) }), idx < items.length - 1 && _jsx(ItemSeparator, {})] }), idx))) }) })));
|
|
70
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Breadcrumbs";
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
|
+
import { stateFocus } from "../styles/styled";
|
|
3
|
+
/**
|
|
4
|
+
* Prevent 300ms delay with `touch-action` performance optimization,
|
|
5
|
+
* @see https://twitter.com/argyleink/status/1405881231695302659
|
|
6
|
+
*/
|
|
7
|
+
export const btnStyleUndo = css `
|
|
8
|
+
appearance: none;
|
|
9
|
+
-webkit-appearance: none;
|
|
10
|
+
-webkit-touch-callout: none;
|
|
11
|
+
user-select: none;
|
|
12
|
+
touch-action: manipulation;
|
|
13
|
+
outline: 0px;
|
|
14
|
+
color: var(--bodyColor);
|
|
15
|
+
`;
|
|
16
|
+
export const btnStyleReset = css `
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
background: transparent;
|
|
21
|
+
border-width: 1px;
|
|
22
|
+
border-style: solid;
|
|
23
|
+
border-color: transparent;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
${btnStyleUndo}
|
|
26
|
+
|
|
27
|
+
&[disabled] {
|
|
28
|
+
cursor: default;
|
|
29
|
+
opacity: 0.7;
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
export const btnStyleBase = css `
|
|
33
|
+
${btnStyleReset}
|
|
34
|
+
|
|
35
|
+
min-width: ${(p) => (p.$noGutter ? "0" : "150px")};
|
|
36
|
+
padding: ${(p) => (p.$noGutter ? "0" : "10px 30px")};
|
|
37
|
+
border-radius: 0;
|
|
38
|
+
text-align: center;
|
|
39
|
+
text-transform: uppercase;
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
${(p) => p.$block && `width: 100%; display: flex;`}
|
|
42
|
+
|
|
43
|
+
&:focus,
|
|
44
|
+
&:active,
|
|
45
|
+
&:visited {
|
|
46
|
+
${stateFocus}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* This targets icons within a button */
|
|
50
|
+
& svg {
|
|
51
|
+
margin: 0 1em 0 0;
|
|
52
|
+
font-size: 1.25em;
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
export const btnStyleContained = css `
|
|
56
|
+
color: white;
|
|
57
|
+
background: var(--accent200);
|
|
58
|
+
border-color: var(--accent200);
|
|
59
|
+
|
|
60
|
+
&:hover:not([disabled]) {
|
|
61
|
+
background: var(--accent300);
|
|
62
|
+
border-color: var(--accent300);
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
export const btnStyleOutlined = css `
|
|
66
|
+
color: var(--accent200);
|
|
67
|
+
border-color: var(--accent200);
|
|
68
|
+
|
|
69
|
+
&:hover:not([disabled]) {
|
|
70
|
+
background: var(--accent300);
|
|
71
|
+
border-color: var(--accent300);
|
|
72
|
+
color: white;
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
export const KoineButton = styled.button `
|
|
76
|
+
${btnStyleBase}
|
|
77
|
+
${(p) => p.$variant === "outlined" && btnStyleOutlined}
|
|
78
|
+
${(p) => p.$variant === "contained" && btnStyleContained}
|
|
79
|
+
`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { IconBaseProps, IconType } from "
|
|
2
|
+
import { IconBaseProps, IconType } from "react-icons/lib";
|
|
3
3
|
import { KoineComponentProps, KoineComponent } from "../types";
|
|
4
4
|
import { KoineButtonProps } from "./Button";
|
|
5
5
|
import { ButtonLinkProps } from "./ButtonLink";
|