nitro-web 0.0.86 → 0.0.87

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 (41) hide show
  1. package/client/globals.ts +10 -6
  2. package/package.json +14 -6
  3. package/types/{required-globals.d.ts → globals.d.ts} +3 -1
  4. package/.editorconfig +0 -9
  5. package/components/auth/auth.api.js +0 -411
  6. package/components/auth/reset.tsx +0 -86
  7. package/components/auth/signin.tsx +0 -76
  8. package/components/auth/signup.tsx +0 -62
  9. package/components/billing/stripe.api.js +0 -268
  10. package/components/dashboard/dashboard.tsx +0 -32
  11. package/components/partials/element/accordion.tsx +0 -102
  12. package/components/partials/element/avatar.tsx +0 -40
  13. package/components/partials/element/button.tsx +0 -98
  14. package/components/partials/element/calendar.tsx +0 -125
  15. package/components/partials/element/dropdown.tsx +0 -248
  16. package/components/partials/element/filters.tsx +0 -194
  17. package/components/partials/element/github-link.tsx +0 -16
  18. package/components/partials/element/initials.tsx +0 -66
  19. package/components/partials/element/message.tsx +0 -141
  20. package/components/partials/element/modal.tsx +0 -90
  21. package/components/partials/element/sidebar.tsx +0 -195
  22. package/components/partials/element/tooltip.tsx +0 -154
  23. package/components/partials/element/topbar.tsx +0 -15
  24. package/components/partials/form/checkbox.tsx +0 -150
  25. package/components/partials/form/drop-handler.tsx +0 -68
  26. package/components/partials/form/drop.tsx +0 -141
  27. package/components/partials/form/field-color.tsx +0 -86
  28. package/components/partials/form/field-currency.tsx +0 -158
  29. package/components/partials/form/field-date.tsx +0 -252
  30. package/components/partials/form/field.tsx +0 -231
  31. package/components/partials/form/form-error.tsx +0 -27
  32. package/components/partials/form/location.tsx +0 -225
  33. package/components/partials/form/select.tsx +0 -360
  34. package/components/partials/is-first-render.ts +0 -14
  35. package/components/partials/not-found.tsx +0 -7
  36. package/components/partials/styleguide.tsx +0 -407
  37. package/semver-updater.cjs +0 -13
  38. package/tsconfig.json +0 -38
  39. package/tsconfig.types.json +0 -15
  40. package/types/core-only-globals.d.ts +0 -9
  41. package/types.ts +0 -60
@@ -1,125 +0,0 @@
1
- import { DayPicker, getDefaultClassNames } from 'react-day-picker'
2
- import { isValid } from 'date-fns'
3
- import 'react-day-picker/style.css'
4
- import { IsFirstRender } from 'nitro-web'
5
-
6
- export const dayButtonClassName = 'size-[33px] text-sm'
7
-
8
- type Mode = 'single'|'multiple'|'range'
9
- type ModeSelection<T extends Mode> = (
10
- T extends 'single' ? Date | undefined
11
- : T extends 'multiple' ? Date[]
12
- : { from?: Date; to?: Date }
13
- )
14
-
15
- export type CalendarProps = {
16
- mode?: Mode
17
- onChange?: (mode: Mode, value: null|number|(null|number)[]) => void
18
- value?: null|number|string|(null|number|string)[]
19
- numberOfMonths?: number
20
- month?: number // the value may be updated from an outside source, thus the month may have changed
21
- className?: string
22
- preserveTime?: boolean // just for single mode
23
- }
24
-
25
- export function Calendar({ mode='single', onChange, value, numberOfMonths, month: monthProp, className, preserveTime }: CalendarProps) {
26
- const isFirstRender = IsFirstRender()
27
- const isRange = mode == 'range'
28
-
29
- // Convert the value to an array of valid* dates
30
- const dates = useMemo(() => {
31
- const _dates = Array.isArray(value) ? value : [value]
32
- return _dates.map(date => isValid(date) ? new Date(date as number) : undefined) ////change to null
33
- }, [value])
34
-
35
- // Hold the month in state to control the calendar when the input changes
36
- const [month, setMonth] = useState(dates[0])
37
-
38
- // Update the month if its changed from an outside source
39
- useEffect(() => {
40
- if (!isFirstRender && monthProp) setMonth(new Date(monthProp))
41
- }, [monthProp])
42
-
43
- function handleDayPickerSelect<T extends Mode>(newDate: ModeSelection<T>) {
44
- switch (mode as T) {
45
- case 'single': {
46
- const date = newDate as ModeSelection<'single'>
47
- preserveTimeFn(date)
48
- onChange?.(mode, date?.getTime() ?? null)
49
- break
50
- }
51
- case 'range': {
52
- const { from, to } = (newDate ?? {}) as ModeSelection<'range'>
53
- onChange?.(mode, from ? [from.getTime() || null, to?.getTime() || null] : null)
54
- break
55
- }
56
- case 'multiple': {
57
- const dates = (newDate as ModeSelection<'multiple'>)?.filter(Boolean) ?? []
58
- onChange?.(mode, dates.map((d) => d.getTime()))
59
- break
60
- }
61
- }
62
- }
63
-
64
- function preserveTimeFn(date?: Date) {
65
- // Preserve time from the original date if needed
66
- if (preserveTime && dates[0] && date) {
67
- const originalDate = dates[0]
68
- date.setHours(
69
- originalDate.getHours(),
70
- originalDate.getMinutes(),
71
- originalDate.getSeconds(),
72
- originalDate.getMilliseconds()
73
- )
74
- }
75
- }
76
-
77
- const d = getDefaultClassNames()
78
- const common = {
79
- month: month,
80
- onMonthChange: setMonth,
81
- onSelect: handleDayPickerSelect,
82
- numberOfMonths: numberOfMonths || (isRange ? 2 : 1),
83
- modifiersClassNames: {
84
- // Add a class without _, TW seems to replace this with a space in the css definition, e.g. &:not(.range middle)
85
- range_middle: `${d.range_middle} rangemiddle`,
86
- },
87
- classNames: {
88
- root: `${d.root} flex nitro-calendar`,
89
- months: `${d.months} flex-nowrap`,
90
- month_caption: `${d.month_caption} text-2xs pl-2`,
91
- caption_label: `${d.caption_label} z-auto`,
92
- button_previous: `${d.button_previous} size-8`,// [&:hover>svg]:fill-input-border-focus`,
93
- button_next: `${d.button_next} size-8`,// [&:hover>svg]:fill-input-border-focus`,
94
- chevron: `${d.chevron} fill-black size-[18px]`,
95
-
96
- // Days
97
- weekday: `${d.weekday} text-[11px] font-bold uppercase`,
98
- day: `${d.day} size-[33px]`,
99
- day_button: `${d.day_button} ${dayButtonClassName}`,
100
-
101
- // States
102
- focused: `${d.focused} [&>button]:bg-gray-200 [&>button]:border-gray-200`,
103
- range_start: `${d.range_start} [&>button]:!bg-input-border-focus [&>button]:!border-input-border-focus`,
104
- range_end: `${d.range_end} [&>button]:!bg-input-border-focus [&>button]:!border-input-border-focus`,
105
- selected: `${d.selected} font-normal `
106
- + '[&:not(.rangemiddle)>button]:!text-white '
107
- + '[&:not(.rangemiddle)>button]:!bg-input-border-focus '
108
- + '[&:not(.rangemiddle)>button]:!border-input-border-focus ',
109
- },
110
- }
111
-
112
- return (
113
- <div>
114
- {
115
- mode === 'single' ? (
116
- <DayPicker mode="single" selected={dates[0]} {...common} className={className} />
117
- ) : mode === 'range' ? (
118
- <DayPicker mode="range" selected={{ from: dates[0], to: dates[1] }} {...common} className={className} />
119
- ) : (
120
- <DayPicker mode="multiple" selected={dates.filter((d) => !!d)} {...common} className={className} />
121
- )
122
- }
123
- </div>
124
- )
125
- }
@@ -1,248 +0,0 @@
1
- import { css } from 'twin.macro'
2
- import { forwardRef, cloneElement } from 'react'
3
- import { getSelectStyle, twMerge } from 'nitro-web'
4
- import { CheckCircleIcon } from '@heroicons/react/24/solid'
5
-
6
- type DropdownProps = {
7
- allowOverflow?: boolean
8
- animate?: boolean
9
- children?: React.ReactNode
10
- className?: string
11
- css?: string
12
- /** The direction of the menu **/
13
- dir?: 'bottom-left'|'bottom-right'|'top-left'|'top-right'
14
- options?: { label: string|React.ReactNode, onClick?: Function, isSelected?: boolean, icon?: React.ReactNode, className?: string }[]
15
- /** Whether the dropdown is hoverable **/
16
- isHoverable?: boolean
17
- /** The content to render inside the top of the dropdown **/
18
- menuContent?: React.ReactNode
19
- menuClassName?: string
20
- menuOptionClassName?: string
21
- menuIsOpen?: boolean
22
- menuToggles?: boolean
23
- /** The minimum width of the menu **/
24
- minWidth?: number | string
25
- toggleCallback?: (isActive: boolean) => void
26
- }
27
-
28
- export const Dropdown = forwardRef(function Dropdown({
29
- allowOverflow=false,
30
- animate=true,
31
- children,
32
- className,
33
- dir='bottom-left',
34
- options,
35
- isHoverable,
36
- menuClassName,
37
- menuOptionClassName,
38
- menuContent,
39
- menuIsOpen,
40
- menuToggles=true,
41
- minWidth,
42
- toggleCallback,
43
- }: DropdownProps, ref) {
44
- // https://letsbuildui.dev/articles/building-a-dropdown-menu-component-with-react-hooks
45
- isHoverable = isHoverable && !menuIsOpen
46
- const dropdownRef = useRef<HTMLDivElement|null>(null)
47
- const [isActive, setIsActive] = useState(!!menuIsOpen)
48
- const menuStyle = getSelectStyle({ name: 'menu' })
49
- const [direction, setDirection] = useState<null | 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'>(null)
50
- const [ready, setReady] = useState(false)
51
-
52
- // Expose the setIsActive function to the parent component
53
- useImperativeHandle(ref, () => ({ setIsActive }))
54
-
55
- useEffect(() => {
56
- const pageClick = (event: MouseEvent | FocusEvent) => {
57
- try {
58
- // If the active element exists and is clicked outside of the dropdown, toggle the dropdown
59
- if (dropdownRef.current !== null && !dropdownRef.current.contains(event.target as Node)) setIsActive(!isActive)
60
- } catch (_e) {
61
- // Errors throw for contains() when the user clicks off the webpage when open
62
- setIsActive(!isActive)
63
- }
64
- }
65
- if (isActive && !menuIsOpen) {
66
- // Wait for the next event loop in the case of mousedown'ing the dropdown, while loosing click focus from a checkbox
67
- setTimeout(() => {
68
- window.addEventListener('mousedown', pageClick)
69
- window.addEventListener('focus', pageClick, true) // true needed to capture focus events
70
- }, 0)
71
- }
72
- return () => {
73
- window.removeEventListener('mousedown', pageClick)
74
- window.removeEventListener('focus', pageClick, true) // true needed to capture focus events
75
- }
76
- }, [isActive, dropdownRef])
77
-
78
- useEffect(() => {
79
- if (toggleCallback) toggleCallback(isActive)
80
- }, [isActive])
81
-
82
- useEffect(() => {
83
- setReady(false)
84
- if (!isActive || !dropdownRef.current) return
85
-
86
- const ul = dropdownRef.current.querySelector('ul') as HTMLElement
87
- if (!ul) return
88
-
89
- // Temporarily show the ul for measurement
90
- const originalMaxHeight = ul.style.maxHeight
91
- const originalVisibility = ul.style.visibility
92
- const originalOpacity = ul.style.opacity
93
- const originalPointerEvents = ul.style.pointerEvents
94
-
95
- ul.style.maxHeight = 'none'
96
- ul.style.visibility = 'hidden'
97
- ul.style.opacity = '0'
98
- ul.style.pointerEvents = 'none'
99
-
100
- const dropdownHeight = ul.getBoundingClientRect().height
101
-
102
- // Revert styles
103
- ul.style.maxHeight = originalMaxHeight
104
- ul.style.visibility = originalVisibility
105
- ul.style.opacity = originalOpacity
106
- ul.style.pointerEvents = originalPointerEvents
107
-
108
- const rect = dropdownRef.current.getBoundingClientRect()
109
- const spaceBelow = window.innerHeight - rect.bottom
110
- const spaceAbove = rect.top
111
-
112
- const side = dir.endsWith('right') ? 'right' : 'left'
113
-
114
- const newDirection = dir.startsWith('bottom')
115
- ? `${spaceBelow < dropdownHeight && spaceAbove > dropdownHeight ? 'top' : 'bottom'}-${side}`
116
- : `${spaceAbove < dropdownHeight && spaceBelow > dropdownHeight ? 'bottom' : 'top'}-${side}`
117
-
118
- setDirection(newDirection as 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right')
119
-
120
- requestAnimationFrame(() => {
121
- setReady(true)
122
- })
123
- }, [isActive, dir])
124
-
125
- function onMouseDown(e: { key: string, preventDefault: Function }) {
126
- if (e.key && e.key != 'Enter') return
127
- if (e.key) e.preventDefault() // for button, stops buttons firing twice
128
- if (!isHoverable && !menuIsOpen && ((menuToggles || e.key) || !isActive)) setIsActive(!isActive)
129
- }
130
-
131
- function onClick(option: { onClick?: Function }, e: React.MouseEvent) {
132
- if (option.onClick) option.onClick(e)
133
- if (!menuIsOpen) setIsActive(!isActive)
134
- }
135
-
136
- return (
137
- <div
138
- class={
139
- `relative is-${direction || dir}` + // until hovered, show the original direction to prevent scrollbars
140
- (isHoverable ? ' is-hoverable' : '') +
141
- (isActive ? ' is-active' : '') +
142
- (!animate ? ' no-animation' : '') +
143
- (allowOverflow ? ' is-allowOverflow' : '') +
144
- ' nitro-dropdown' +
145
- (className ? ` ${className}` : '')
146
- }
147
- onClick={(e) => e.stopPropagation()} // required for dropdowns inside row links
148
- ref={dropdownRef}
149
- css={style}
150
- >
151
- {
152
- (Array.isArray(children) ? children : [children]).map((el, key) => {
153
- const onKeyDown = onMouseDown
154
- if (!el.type) throw new Error('Dropdown component requires a valid child element')
155
- return cloneElement(el, { key, onMouseDown, onKeyDown }) // adds onClick
156
- })
157
- }
158
- <ul
159
- style={{ minWidth }}
160
- class={
161
- twMerge(`${menuStyle} ${ready ? 'is-ready' : ''} absolute invisible opacity-0 select-none min-w-full z-[1] ${menuClassName||''}`)}
162
- >
163
- {menuContent}
164
- {
165
- options && options.map((option, i) => {
166
- const optionStyle = getSelectStyle({ name: 'option', usePrefixes: true, isSelected: option.isSelected })
167
- return (
168
- <li
169
- key={i}
170
- className={twMerge(`${optionStyle} ${option.className} ${menuOptionClassName}`)}
171
- onClick={(e: React.MouseEvent) => onClick(option, e)}
172
- >
173
- <span class="flex-auto">{option.label}</span>
174
- { !!option.icon && option.icon }
175
- { option.isSelected && <CheckCircleIcon className="size-[22px] text-primary -my-1 -mx-0.5" /> }
176
- </li>
177
- )
178
- })
179
- }
180
- </ul>
181
- </div>
182
- )
183
- })
184
-
185
- const style = css`
186
- &>ul {
187
- transition: transform 0.15s ease, opacity 0.15s ease, visibility 0s 0.15s ease, max-width 0s 0.15s ease, max-height 0s 0.15s ease;
188
- max-width: 0; // handy if the dropdown ul exceeds the viewport width
189
- max-height: 0; // handy if the dropdown ul exceeds the viewport height
190
- pointer-events: none;
191
- }
192
- &.is-bottom-right,
193
- &.is-top-right {
194
- ul {
195
- left: auto;
196
- right: 0;
197
- }
198
- }
199
- &.is-bottom-left,
200
- &.is-bottom-right {
201
- &>ul {
202
- top: 100%;
203
- transform: translateY(6px);
204
- }
205
- }
206
- &.is-top-left,
207
- &.is-top-right {
208
- &>ul {
209
- bottom: 100%;
210
- transform: translateY(-10px);
211
- }
212
- }
213
- // active submenu
214
- &.is-hoverable:hover,
215
- &:focus,
216
- &.is-active,
217
- &>ul>li:hover,
218
- &>ul>li:focus,
219
- &>ul>li.is-active {
220
- &>ul.is-ready {
221
- opacity: 1;
222
- visibility: visible;
223
- transition: transform 0.15s ease, opacity 0.15s ease;
224
- max-width: 1000px;
225
- max-height: 1000px;
226
- pointer-events: auto;
227
- }
228
- &.is-allowOverflow > ul {
229
- overflow: visible;
230
- }
231
- &.is-bottom-left > ul,
232
- &.is-bottom-right > ul {
233
- transform: translateY(3px) !important;
234
- }
235
- &.is-top-left > ul,
236
- &.is-top-right > ul {
237
- transform: translateY(-7px) !important;
238
- }
239
- }
240
- // no animation
241
- &.no-animation {
242
- &>ul {
243
- transition: none;
244
- }
245
- }
246
- `
247
-
248
-
@@ -1,194 +0,0 @@
1
- import { forwardRef, Dispatch, SetStateAction, useRef, useEffect, useImperativeHandle } from 'react'
2
- import { Button, Dropdown, Field, Select, type FieldProps, type SelectProps } from 'nitro-web'
3
- import { camelCaseToTitle, debounce, omit, queryString, queryObject, twMerge } from 'nitro-web/util'
4
- import { ListFilterIcon } from 'lucide-react'
5
-
6
- type CommonProps = {
7
- label?: string
8
- rowClassName?: string
9
- }
10
- export type FilterType = (
11
- | FieldProps & CommonProps
12
- | ({ type: 'select' } & SelectProps & CommonProps)
13
- )
14
-
15
- type FilterState = {
16
- [key: string]: string | true
17
- }
18
-
19
- type FiltersProps = {
20
- state?: FilterState
21
- setState?: Dispatch<SetStateAction<FilterState>>
22
- filters?: FilterType[]
23
- elements?: {
24
- Button?: typeof Button
25
- Dropdown?: typeof Dropdown
26
- Field?: typeof Field
27
- Select?: typeof Select
28
- FilterIcon?: typeof ListFilterIcon
29
- }
30
- buttonProps?: Partial<React.ComponentProps<typeof Button>>
31
- buttonText?: string
32
- buttonCounterClassName?: string
33
- dropdownProps?: Partial<React.ComponentProps<typeof Dropdown>>
34
- dropdownFiltersClassName?: string
35
- }
36
-
37
- export type FiltersHandleType = {
38
- submit: (includePagination?: boolean) => void
39
- }
40
-
41
- const debounceTime = 250
42
-
43
- export const Filters = forwardRef<FiltersHandleType, FiltersProps>(({
44
- filters,
45
- setState: setState2,
46
- state: state2,
47
- buttonProps,
48
- buttonCounterClassName,
49
- buttonText,
50
- dropdownProps,
51
- dropdownFiltersClassName,
52
- elements,
53
- }, ref) => {
54
- const location = useLocation()
55
- const navigate = useNavigate()
56
- const [lastUpdated, setLastUpdated] = useState(0)
57
- const [debouncedSubmit] = useState(() => debounce(submit, debounceTime))
58
- const [state3, setState3] = useState(() => ({ ...queryObject(location.search) }))
59
- const [state, setState] = [state2 || state3, setState2 || setState3]
60
- const stateRef = useRef(state)
61
- const count = useMemo(() => Object.keys(state).filter((k) => state[k] && filters?.some((f) => f.name === k)).length, [state, filters])
62
-
63
- const Elements = {
64
- Button: elements?.Button || Button,
65
- Dropdown: elements?.Dropdown || Dropdown,
66
- Field: elements?.Field || Field,
67
- Select: elements?.Select || Select,
68
- FilterIcon: elements?.FilterIcon || ListFilterIcon,
69
- }
70
-
71
- useImperativeHandle(ref, () => ({
72
- submit: debouncedSubmit,
73
- }))
74
-
75
- useEffect(() => {
76
- return () => debouncedSubmit.cancel()
77
- }, [])
78
-
79
- useEffect(() => {
80
- stateRef.current = state
81
- }, [state])
82
-
83
- useEffect(() => {
84
- // Only update the state if the filters haven't been input changed in the last 500ms
85
- if (Date.now() - lastUpdated > (debounceTime + 250)) {
86
- setState(() => ({
87
- ...queryObject(location.search),
88
- }))
89
- }
90
- }, [location.search])
91
-
92
- function reset(e: React.MouseEvent<HTMLAnchorElement>, filter: FilterType) {
93
- e.preventDefault()
94
- setState((s) => omit(s, [filter.name]) as FilterState)
95
- onAfterChange()
96
- }
97
-
98
- function resetAll(e: React.MouseEvent<HTMLButtonElement>) {
99
- e.preventDefault()
100
- setState((s) => omit(s, filters?.map((f) => f.name) || []) as FilterState)
101
- onAfterChange()
102
- }
103
-
104
- async function onInputChange(e: {target: {name: string, value: unknown}}) {
105
- // basic name and value (keeping deep paths intact e.g. 'jobCache.location': '10')
106
- setState((s) => ({ ...s, [e.target.name]: e.target.value as string }))
107
- onAfterChange()
108
- }
109
-
110
- function onAfterChange() {
111
- setLastUpdated(Date.now())
112
- debouncedSubmit()
113
- }
114
-
115
- // Update the URL by replacing the current entry in the history stack
116
- function submit(includePagination?: boolean) {
117
- const queryStr = queryString(omit(stateRef.current, includePagination ? [] : ['page']))
118
- navigate(location.pathname + queryStr, { replace: true })
119
- }
120
-
121
- return (
122
- <Elements.Dropdown
123
- // menuIsOpen={true}
124
- dir="bottom-right"
125
- allowOverflow={true}
126
- {...dropdownProps}
127
- menuClassName={twMerge(`min-w-[330px] ${dropdownProps?.menuClassName || ''}`)}
128
- menuContent={
129
- <div>
130
- <div class="flex justify-between items-center border-b p-4 py-3.5">
131
- <div class="text-lg font-semibold">Filters</div>
132
- <Button color="clear" size="sm" onClick={resetAll}>Reset All</Button>
133
- </div>
134
- {/* <div class="w-[1330px] bg-red-500 absolute">
135
- This div shouldnt produce a page scrollbar when the dropdown is closed.
136
- But should be visibile if allowedOverflow is true.
137
- </div> */}
138
- <div class={twMerge(`flex flex-wrap gap-4 px-4 py-4 pb-6 ${dropdownFiltersClassName || ''}`)}>
139
- {
140
- filters?.map(({label, rowClassName, ...filter}, i) => (
141
- <div key={i} class={twMerge(`w-full ${rowClassName||''}`)}>
142
- <div class="flex justify-between">
143
- <label for={filter.id || filter.name}>{label || camelCaseToTitle(filter.name)}</label>
144
- <a href="#" class="label font-normal text-secondary underline" onClick={(e) => reset(e, filter)}>Reset</a>
145
- </div>
146
- {
147
- filter.type === 'select' &&
148
- <Elements.Select
149
- {...filter}
150
- class="!mb-0"
151
- value={state[filter.name] || ''}
152
- onChange={onInputChange}
153
- type={undefined}
154
- />
155
- }
156
- {
157
- filter.type !== 'select' &&
158
- <Elements.Field
159
- {...filter}
160
- class="!mb-0"
161
- value={(state[filter.name] as string) || ''}
162
- onChange={onInputChange}
163
- />
164
- }
165
- </div>
166
- ))
167
- }
168
- </div>
169
- </div>
170
- }
171
- >
172
- <Elements.Button
173
- color="white"
174
- IconLeft={<Elements.FilterIcon size={16} />}
175
- {...buttonProps}
176
- className={twMerge(`flex gap-x-2.5 ${buttonProps?.className || ''}`)}
177
- >
178
- <span class="flex items-center gap-x-2.5">
179
- { buttonText || 'Filter By' }
180
- {
181
- !!count &&
182
- <span
183
- class={twMerge(`inline-flex items-center justify-center rounded-full text-white bg-primary box-content w-[1em] h-[1em] p-[2px] ${buttonCounterClassName || ''}`)}
184
- >
185
- <span class="text-xs">{count}</span>
186
- </span>
187
- }
188
- </span>
189
- </Elements.Button>
190
- </Elements.Dropdown>
191
- )
192
- })
193
-
194
- Filters.displayName = 'Filters'
@@ -1,16 +0,0 @@
1
- import GithubIcon from 'nitro-web/client/imgs/github.svg'
2
-
3
- export function GithubLink({ filename }: { filename: string }) {
4
- const base = 'https://github.com/boycce/nitro-web/blob/master/packages/'
5
- // Filenames are relative to the webpack start directory
6
- // 1. Remove ../ from filename (i.e. for _example build)
7
- // 2. Remove node_modules/nitro-web/ from filename (i.e. for packages using nitro-web)
8
- const link = base + filename.replace(/^(\.\.\/|.*node_modules\/nitro-web\/)/, '')
9
-
10
- return (
11
- // <a href={link}>Go to Github</a>
12
- <a href={link} className="fixed top-0 right-0 nitro-github">
13
- <GithubIcon />
14
- </a>
15
- )
16
- }
@@ -1,66 +0,0 @@
1
- import { css } from 'twin.macro'
2
-
3
- type InitialsProps = {
4
- icon?: { initials: string, hex: string }
5
- isBig?: boolean
6
- isMedium?: boolean
7
- isSmall?: boolean
8
- isRound?: boolean
9
- className?: string
10
- }
11
-
12
- export function Initials({ icon, isBig, isMedium, isSmall, isRound, className }: InitialsProps) {
13
- return (
14
- <span
15
- css={style}
16
- class={
17
- 'initials-square' +
18
- (isBig ? ' is-big' : '') +
19
- (isMedium ? ' is-medium' : '') +
20
- (isSmall ? ' is-small' : '') +
21
- (isRound ? ' is-round' : '') +
22
- (icon ? '' : ' is-empty') +
23
- ' nitro-initials' +
24
- (className ? ' ' + className : '')
25
- }
26
- style={icon ? {backgroundColor: icon?.hex + '15', color: icon?.hex} : {}}
27
- >
28
- {icon?.initials}
29
- </span>
30
- )
31
- }
32
-
33
- const style = css`
34
- // seen in input.jsx
35
- display: flex;
36
- align-items: center;
37
- justify-content: center;
38
- border-radius: 5px;
39
- font-weight: 700;
40
- font-size: 11px;
41
- width: 24px;
42
- height: 24px;
43
- // new
44
- &.is-medium {
45
- width: 30px;
46
- height: 30px;
47
- font-size: 12px;
48
- }
49
- // seen in select.jsx
50
- &.is-small {
51
- width: 22px;
52
- height: 22px;
53
- font-size: 11px;
54
- }
55
- &.is-big {
56
- width: 48px;
57
- height: 48px;
58
- font-size: 14px;
59
- }
60
- &.is-round {
61
- border-radius: 50%;
62
- }
63
- &.is-empty {
64
- width: 0;
65
- }
66
- `