@brainfish-ai/components 0.24.4 → 0.24.6
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/esm/chunks/{ChatSearch.DvpPvB5F.js → ChatSearch.s2AQdrx5.js} +7 -7
- package/dist/esm/chunks/{ChatSearch.DvpPvB5F.js.map → ChatSearch.s2AQdrx5.js.map} +1 -1
- package/dist/esm/chunks/{FormattedMessage.Br7XTLD2.js → FormattedMessage.CRbM-hF6.js} +2 -2
- package/dist/esm/chunks/{FormattedMessage.Br7XTLD2.js.map → FormattedMessage.CRbM-hF6.js.map} +1 -1
- package/dist/esm/chunks/button.DQL6gCAt.js +48 -0
- package/dist/esm/chunks/button.DQL6gCAt.js.map +1 -0
- package/dist/esm/chunks/{combobox.DNYCWyub.js → combobox.BpGnNZ6a.js} +2 -2
- package/dist/esm/chunks/{combobox.DNYCWyub.js.map → combobox.BpGnNZ6a.js.map} +1 -1
- package/dist/esm/chunks/{date-picker.sQXSlqNZ.js → date-picker._cBTpdEK.js} +2 -2
- package/dist/esm/chunks/{date-picker.sQXSlqNZ.js.map → date-picker._cBTpdEK.js.map} +1 -1
- package/dist/esm/chunks/{feedback.D139-1Wr.js → feedback.W2OzN-5r.js} +2 -2
- package/dist/esm/chunks/{feedback.D139-1Wr.js.map → feedback.W2OzN-5r.js.map} +1 -1
- package/dist/esm/chunks/{file-upload-status.Vw0Zxmir.js → file-upload-status.DP2iuttI.js} +2 -2
- package/dist/esm/chunks/{file-upload-status.Vw0Zxmir.js.map → file-upload-status.DP2iuttI.js.map} +1 -1
- package/dist/esm/chunks/{filters.Be4KPvMA.js → filters.LuyM6z8R.js} +2 -2
- package/dist/esm/chunks/{filters.Be4KPvMA.js.map → filters.LuyM6z8R.js.map} +1 -1
- package/dist/esm/chunks/{font-picker.DX1mER3H.js → font-picker.CtGg-OWt.js} +2 -2
- package/dist/esm/chunks/{font-picker.DX1mER3H.js.map → font-picker.CtGg-OWt.js.map} +1 -1
- package/dist/esm/chunks/{header-nav.BxK3FN1j.js → header-nav.C1uX9mgG.js} +2 -2
- package/dist/esm/chunks/{header-nav.BxK3FN1j.js.map → header-nav.C1uX9mgG.js.map} +1 -1
- package/dist/esm/chunks/{layout.Dx6MGe6T.js → layout.CLxqWeQt.js} +3 -3
- package/dist/esm/chunks/{layout.Dx6MGe6T.js.map → layout.CLxqWeQt.js.map} +1 -1
- package/dist/esm/chunks/{sidebar.zsMK3xuM.js → sidebar.CYhTQT2L.js} +2 -2
- package/dist/esm/chunks/{sidebar.zsMK3xuM.js.map → sidebar.CYhTQT2L.js.map} +1 -1
- package/dist/esm/chunks/{two-level-combobox.DsWPDcI6.js → two-level-combobox.BXs2z9u5.js} +2 -2
- package/dist/esm/chunks/{two-level-combobox.DsWPDcI6.js.map → two-level-combobox.BXs2z9u5.js.map} +1 -1
- package/dist/esm/components/article-suggestions-banner.js +1 -1
- package/dist/esm/components/chat-search.js +1 -1
- package/dist/esm/components/combobox.js +1 -1
- package/dist/esm/components/convos.js +2 -2
- package/dist/esm/components/date-picker.js +1 -1
- package/dist/esm/components/feedback.js +1 -1
- package/dist/esm/components/file-upload.js +1 -1
- package/dist/esm/components/filter.js +1 -1
- package/dist/esm/components/font-picker.js +1 -1
- package/dist/esm/components/markdown.js +1 -1
- package/dist/esm/components/two-level-combobox.js +1 -1
- package/dist/esm/components/ui/alert-dialog.js +1 -1
- package/dist/esm/components/ui/button.js +5 -45
- package/dist/esm/components/ui/button.js.map +1 -1
- package/dist/esm/components/ui/select.js +3 -17
- package/dist/esm/components/ui/select.js.map +1 -1
- package/dist/esm/components/ui/sheet.js +1 -1
- package/dist/esm/global.css +1 -1
- package/dist/esm/index.js +14 -14
- package/dist/esm/layouts/full-layout.js +2 -2
- package/dist/esm/layouts/header-nav.js +1 -1
- package/dist/esm/layouts/sidebar.js +1 -1
- package/dist/esm/scenes/knowledge-review.js +24 -36
- package/dist/esm/scenes/knowledge-review.js.map +1 -1
- package/dist/esm/tailwind.preset.js +9 -1
- package/dist/esm/tailwind.preset.js.map +1 -1
- package/dist/stats.html +1 -1
- package/package.json +1 -1
- package/tailwind.preset.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.Be4KPvMA.js","sources":["../../../src/components/filter/types.ts","../../../src/components/filter/hooks.ts","../../../src/components/filter/components/CustomValueInput.tsx","../../../src/components/filter/components/MultiSelectDropdown.tsx","../../../src/components/filter/components/SingleSelectDropdown.tsx","../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["// Types\nexport interface FilterOption {\n id: string;\n label: string;\n}\n\nexport enum Operator {\n IS = 'is',\n IS_NOT = 'is not',\n CONTAINS = 'contains',\n DOES_NOT_CONTAIN = 'does not contain',\n STARTS_WITH = 'starts with',\n}\n\nexport interface FilterValue {\n id: string | number;\n source?: string;\n operator?: Operator;\n value?: string | string[];\n}\n\n/**\n * Filter rules for each source\n * How this works:\n * - You can define the rules for each source\n * - The rules are used to determine the available operators and value type\n * - The input type is used to determine the type of input displayed in when the dropdown is opened\n * - The getValueOptions function is used to determine the available options for the value\n * - multiSelect determines if multiple values can be selected for dropdown type\n *\n * @example\n * {\n * 'sourceId': {\n * operators: [\n * { id: 'is', label: 'is' },\n * { id: 'is not', label: 'is not' },\n * ],\n * inputType: 'dropdown' | 'custom',\n * multiSelect?: boolean,\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n multiSelect?: boolean;\n getValueOptions?: () => FilterOption[];\n };\n}\n\nexport interface FilterProps {\n filter: FilterValue;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n onSourceChange?: (sourceId: string) => void;\n onRemoveFilter: (id: string | number) => void;\n onFilterChange: (filter: FilterValue) => void;\n selectPlaceholder?: string;\n customValuePlaceholder?: string;\n customValueButtonLabel?: string;\n sourceFirstMessage?: string;\n}\n","import { FilterValue } from './types';\n\nexport const useMultiSelectHelpers = (\n internalFilter: FilterValue,\n valueOptions: Array<{ id: string; label: string }>,\n selectPlaceholder: string,\n) => {\n const getSelectedValues = (): string[] => {\n if (Array.isArray(internalFilter.value)) {\n return internalFilter.value;\n }\n\n return internalFilter.value ? [internalFilter.value] : [];\n };\n\n const isValueSelected = (valueId: string): boolean => {\n const selectedValues = getSelectedValues();\n\n return selectedValues.includes(valueId);\n };\n\n const getDisplayValue = (): string => {\n const selectedValues = getSelectedValues();\n if (selectedValues.length === 0) return selectPlaceholder;\n if (selectedValues.length === 1) {\n const option = valueOptions.find((opt) => opt.id === selectedValues[0]);\n\n return option?.label || selectedValues[0];\n }\n\n return `${selectedValues.length} selected`;\n };\n\n return {\n getSelectedValues,\n isValueSelected,\n getDisplayValue,\n };\n};\n","import React, { useRef } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\n\ninterface CustomValueInputProps {\n inputValue: string;\n setInputValue: (value: string) => void;\n customValuePlaceholder: string;\n customValueButtonLabel: string;\n onSubmit: () => void;\n handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => void;\n}\n\nexport const CustomValueInput: React.FC<CustomValueInputProps> = ({\n inputValue,\n setInputValue,\n customValuePlaceholder,\n customValueButtonLabel,\n onSubmit,\n handleKeyDown,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder={customValuePlaceholder}\n className=\"mb-2\"\n onKeyDown={(e) => handleKeyDown(e, true)}\n />\n <Button\n type=\"submit\"\n variant=\"dark\"\n className=\"w-full\"\n onKeyDown={(e) => handleKeyDown(e, false)}\n data-custom-submit-button\n >\n {customValueButtonLabel}\n </Button>\n </form>\n );\n};\n","import React, { useState, useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterValue, FilterOption } from '../types';\n\nimport { Button } from '@/components/ui/button';\n\ninterface MultiSelectDropdownProps {\n internalFilter: FilterValue;\n valueOptions: FilterOption[];\n onConfirm: (selectedValues: string[]) => void;\n onClose: () => void;\n}\n\nconst getInitialValues = (value: FilterValue['value']): string[] => {\n if (Array.isArray(value)) {\n return value;\n } else if (value) {\n return [value];\n }\n\n return [];\n};\n\nexport const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({\n internalFilter,\n valueOptions,\n onConfirm,\n onClose,\n}) => {\n const [pendingValues, setPendingValues] = useState<string[]>(() => getInitialValues(internalFilter.value));\n const [announcement, setAnnouncement] = useState<string>('');\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n\n const handleValueToggle = (valueId: string) => {\n const option = valueOptions.find((opt) => opt.id === valueId);\n const isCurrentlySelected = pendingValues.includes(valueId);\n\n setPendingValues((prev) => {\n const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];\n\n // Announce the change\n if (option) {\n const action = isCurrentlySelected ? 'deselected' : 'selected';\n setAnnouncement(`${option.label} ${action}.`);\n }\n\n return newValues;\n });\n };\n\n const handleConfirm = () => {\n onConfirm(pendingValues);\n onClose();\n };\n\n const isValueSelected = (valueId: string): boolean => {\n return pendingValues.includes(valueId);\n };\n\n const focusButton = (index: number) => {\n if (index < valueOptions.length) {\n buttonRefs.current[index]?.focus();\n } else {\n applyButtonRef.current?.focus();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n if (index < valueOptions.length) {\n // If the user is selecting an option\n handleValueToggle(valueOptions[index].id);\n } else {\n // If the user is selecting the apply button\n handleConfirm();\n }\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\" aria-multiselectable=\"true\">\n {/* Screen reader announcements */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => handleValueToggle(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n role=\"option\"\n aria-selected={isValueSelected(option.id)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n\n <div className=\"border-t border-border mt-1 pt-2 px-2 pb-2\">\n <Button\n ref={applyButtonRef}\n onClick={handleConfirm}\n size=\"sm\"\n className=\"w-full\"\n disabled={pendingValues.length === 0}\n onKeyDown={(e) => handleKeyDown(e, valueOptions.length)}\n >\n Apply ({pendingValues.length} selected)\n </Button>\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterOption } from '../types';\n\ninterface SingleSelectDropdownProps {\n valueOptions: FilterOption[];\n isValueSelected: (valueId: string) => boolean;\n onValueSelect: (valueId: string) => void;\n}\n\nexport const SingleSelectDropdown: React.FC<SingleSelectDropdownProps> = ({\n valueOptions,\n isValueSelected,\n onValueSelect,\n}) => {\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const focusButton = (index: number) => {\n buttonRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length - 1);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n onValueSelect(valueOptions[index].id);\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\">\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => onValueSelect(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n </div>\n );\n};\n","import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { FilterProps, FilterValue, Operator } from './types';\nimport { useMultiSelectHelpers } from './hooks';\nimport { CustomValueInput } from './components/CustomValueInput';\nimport { MultiSelectDropdown } from './components/MultiSelectDropdown';\nimport { SingleSelectDropdown } from './components/SingleSelectDropdown';\n\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nconst Filter = forwardRef<{ focus: () => void }, FilterProps>(\n (\n {\n filter,\n sourceOptions,\n rules,\n onSourceChange,\n onRemoveFilter,\n onFilterChange,\n selectPlaceholder = 'Select a value',\n customValuePlaceholder = 'Enter custom value',\n customValueButtonLabel = 'Done',\n sourceFirstMessage = 'Please select a source first',\n }: FilterProps,\n ref,\n ) => {\n // State\n const [internalFilter, setInternalFilter] = useState<FilterValue>({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n const [inputValue, setInputValue] = useState('');\n const [openDropdownType, setOpenDropdownType] = useState<'source' | 'operator' | 'value' | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const sourceButtonRef = useRef<HTMLButtonElement>(null);\n const divRef = useRef<HTMLDivElement>(null);\n\n // Expose focus method\n useImperativeHandle(ref, () => ({\n focus: () => {\n sourceButtonRef.current?.focus();\n },\n }));\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n const isMultiSelect = currentRules?.multiSelect || false;\n let inputType = currentRules?.inputType || 'dropdown';\n if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {\n inputType = 'custom';\n }\n const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];\n\n // Multi-select helpers\n const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(\n internalFilter,\n valueOptions,\n selectPlaceholder,\n );\n\n // Auto-focus input when dropdown opens and custom input is needed\n useEffect(() => {\n if (openDropdownType === 'value' && inputType === 'custom') {\n const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);\n\n return () => clearTimeout(timeoutId);\n }\n\n return undefined;\n }, [openDropdownType, inputType]);\n\n // Sync with external state\n useEffect(() => {\n setInternalFilter({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n }, [filter]);\n\n // Helper function to check if filter is complete and trigger onChange\n const checkAndTriggerChange = (newFilter: FilterValue) => {\n const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();\n\n const isComplete = newFilter.source && newFilter.operator && hasValue;\n\n if (isComplete) {\n onFilterChange(newFilter);\n }\n };\n\n // Handle field updates\n const updateFilterField = (field: keyof FilterValue, value: string) => {\n const newFilter: FilterValue = { ...internalFilter, [field]: value };\n\n // Special handling for source changes\n if (field === 'source') {\n const sourceRules = rules[value];\n newFilter.operator = sourceRules?.operators[0]?.id as Operator;\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n // If operator changes, also clear value if inputType is dropdown\n if (field === 'operator') {\n if (internalFilter.source) {\n const sourceRules = rules[internalFilter.source];\n if (sourceRules?.inputType === 'dropdown') {\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n if (!isMultiSelect || field !== 'value') {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select value changes\n const handleValueToggle = (valueId: string) => {\n const selectedValues = getSelectedValues();\n let newValues: string[];\n\n if (isMultiSelect) {\n if (selectedValues.includes(valueId)) {\n newValues = selectedValues.filter((id) => id !== valueId);\n } else {\n newValues = [...selectedValues, valueId];\n }\n } else {\n newValues = [valueId];\n }\n\n const newFilter = {\n ...internalFilter,\n value: isMultiSelect ? newValues : newValues[0] || '',\n };\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n // Close dropdown for single select, keep open for multi-select\n if (!isMultiSelect) {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select confirmation\n const handleMultiSelectConfirm = (selectedValues: string[]) => {\n const newFilter = {\n ...internalFilter,\n value: selectedValues,\n };\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;\n if (isComplete) onFilterChange(newFilter);\n\n setOpenDropdownType(null);\n };\n\n // Handle custom value submission\n const handleCustomValueSubmit = () => {\n if (inputValue.trim()) {\n const newFilter = { ...internalFilter, value: inputValue.trim() };\n setInternalFilter(newFilter);\n setInputValue('');\n setOpenDropdownType(null);\n if (newFilter.source && newFilter.operator && newFilter.value) {\n onFilterChange(newFilter);\n }\n }\n };\n\n // Tab trap handlers\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => {\n if (e.key === 'Escape') {\n setOpenDropdownType(null);\n\n return;\n }\n if (e.key === 'Tab') {\n if (isInput && !e.shiftKey) {\n e.preventDefault();\n const button = document.querySelector('[data-custom-submit-button]') as HTMLButtonElement;\n button?.focus();\n } else if (!isInput) {\n e.preventDefault();\n inputRef.current?.focus();\n }\n }\n };\n\n return (\n <ButtonGroup\n ref={divRef}\n orientation=\"horizontal\"\n className=\"rounded-full border border-border divide-x-2 divide-dark-500\"\n >\n {/* Source Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'source'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'source' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button ref={sourceButtonRef} variant=\"ghost\" size=\"xs\" className=\"rounded-l-full font-bold\">\n {sourceOptions.find((opt) => opt.id === internalFilter.source)?.label ||\n sourceOptions[0]?.label ||\n selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {sourceOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => {\n updateFilterField('source', option.id);\n onSourceChange?.(option.id);\n }}\n >\n {option.id === internalFilter.source && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Operator Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'operator'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'operator' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\">\n {operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {operatorOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('operator', option.id)}\n >\n {option.id === internalFilter.operator && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Value Popover */}\n <Popover\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n >\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\" className=\"font-bold\">\n {getDisplayValue()}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-0\">\n {inputType === 'custom' && (\n <div className=\"p-3\">\n <CustomValueInput\n inputValue={inputValue}\n setInputValue={setInputValue}\n customValuePlaceholder={customValuePlaceholder}\n customValueButtonLabel={customValueButtonLabel}\n onSubmit={handleCustomValueSubmit}\n handleKeyDown={handleKeyDown}\n />\n </div>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n <>\n {isMultiSelect ? (\n <MultiSelectDropdown\n internalFilter={internalFilter}\n valueOptions={valueOptions}\n onConfirm={handleMultiSelectConfirm}\n onClose={() => setOpenDropdownType(null)}\n />\n ) : (\n <SingleSelectDropdown\n valueOptions={valueOptions}\n isValueSelected={isValueSelected}\n onValueSelect={handleValueToggle}\n />\n )}\n </>\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n setInternalFilter({ id: filter.id });\n setOpenDropdownType(null);\n onRemoveFilter(filter.id);\n }}\n className=\"p-2 hover:bg-black/10 rounded-none rounded-r-full\"\n aria-label=\"Remove filter\"\n >\n <XCircle size={16} weight=\"fill\" />\n </Button>\n </ButtonGroup>\n );\n },\n);\n\nFilter.displayName = 'Filter';\n\nexport { Filter };\n","import React, { useState, useEffect, useRef } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './index';\nimport { Button } from '../ui/button';\n\nimport { cn } from '@/lib/utils';\n\ninterface FiltersProps extends React.HTMLAttributes<HTMLDivElement> {\n filters: FilterValue[];\n onFilterChange: (filter: FilterValue) => void;\n onFilterRemove: (filterId: string | number) => void;\n onFilterAdd?: (filter: FilterValue) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({\n filters,\n onFilterChange,\n onFilterRemove,\n onFilterAdd,\n sourceOptions,\n rules,\n className,\n}: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n const filterRefs = useRef<{ [key: string]: { focus: () => void } | null }>({});\n\n // Sync internal state with props\n useEffect(() => {\n setInternalFilters(filters || []);\n }, [filters]);\n\n // Get sources that are already in use\n const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);\n\n // Get available sources that haven't been used yet\n const availableSources = sourceOptions.filter((option) => {\n // If the source has multiSelect enabled, filter out used sources\n if (rules[option.id]?.multiSelect) {\n return !usedSources.includes(option.id);\n }\n\n // If multiSelect is false or undefined, allow the source to be used multiple times\n return sourceOptions;\n });\n\n // Check if we can add more filters\n const canAddFilter = availableSources.length > 0;\n\n const handleAddFilter = () => {\n if (!canAddFilter) return;\n\n const newFilter = {\n id: createId(),\n source: availableSources[0].id,\n operator: Operator.IS,\n value: rules[availableSources[0].id]?.multiSelect ? [] : '',\n };\n\n const newFilters = [...internalFilters, newFilter];\n setInternalFilters(newFilters);\n\n // Focus the new filter after it's rendered\n requestAnimationFrame(() => {\n filterRefs.current[newFilter.id]?.focus();\n });\n\n // Notify parent if callback provided\n onFilterAdd?.(newFilter);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n const newFilters = internalFilters.filter((f) => f.id !== filter.id);\n setInternalFilters(newFilters);\n onFilterRemove(filter.id);\n };\n\n return (\n <fieldset className={cn('flex flex-wrap gap-2', className)}>\n <legend className=\"sr-only\">Filters</legend>\n {internalFilters?.map((filter) => {\n // For each filter, include available sources plus its own current source\n const filterSourceOptions = sourceOptions.filter(\n (option) =>\n !usedSources.includes(option.id) || // Available sources\n option.id === filter.source, // Or its own current source\n );\n\n return (\n <Filter\n key={filter.id}\n ref={(ref) => {\n filterRefs.current[filter.id] = ref;\n }}\n filter={filter}\n sourceOptions={filterSourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n );\n })}\n {canAddFilter && (\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n title=\"Add filter\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n )}\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"filters.LuyM6z8R.js","sources":["../../../src/components/filter/types.ts","../../../src/components/filter/hooks.ts","../../../src/components/filter/components/CustomValueInput.tsx","../../../src/components/filter/components/MultiSelectDropdown.tsx","../../../src/components/filter/components/SingleSelectDropdown.tsx","../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["// Types\nexport interface FilterOption {\n id: string;\n label: string;\n}\n\nexport enum Operator {\n IS = 'is',\n IS_NOT = 'is not',\n CONTAINS = 'contains',\n DOES_NOT_CONTAIN = 'does not contain',\n STARTS_WITH = 'starts with',\n}\n\nexport interface FilterValue {\n id: string | number;\n source?: string;\n operator?: Operator;\n value?: string | string[];\n}\n\n/**\n * Filter rules for each source\n * How this works:\n * - You can define the rules for each source\n * - The rules are used to determine the available operators and value type\n * - The input type is used to determine the type of input displayed in when the dropdown is opened\n * - The getValueOptions function is used to determine the available options for the value\n * - multiSelect determines if multiple values can be selected for dropdown type\n *\n * @example\n * {\n * 'sourceId': {\n * operators: [\n * { id: 'is', label: 'is' },\n * { id: 'is not', label: 'is not' },\n * ],\n * inputType: 'dropdown' | 'custom',\n * multiSelect?: boolean,\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n multiSelect?: boolean;\n getValueOptions?: () => FilterOption[];\n };\n}\n\nexport interface FilterProps {\n filter: FilterValue;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n onSourceChange?: (sourceId: string) => void;\n onRemoveFilter: (id: string | number) => void;\n onFilterChange: (filter: FilterValue) => void;\n selectPlaceholder?: string;\n customValuePlaceholder?: string;\n customValueButtonLabel?: string;\n sourceFirstMessage?: string;\n}\n","import { FilterValue } from './types';\n\nexport const useMultiSelectHelpers = (\n internalFilter: FilterValue,\n valueOptions: Array<{ id: string; label: string }>,\n selectPlaceholder: string,\n) => {\n const getSelectedValues = (): string[] => {\n if (Array.isArray(internalFilter.value)) {\n return internalFilter.value;\n }\n\n return internalFilter.value ? [internalFilter.value] : [];\n };\n\n const isValueSelected = (valueId: string): boolean => {\n const selectedValues = getSelectedValues();\n\n return selectedValues.includes(valueId);\n };\n\n const getDisplayValue = (): string => {\n const selectedValues = getSelectedValues();\n if (selectedValues.length === 0) return selectPlaceholder;\n if (selectedValues.length === 1) {\n const option = valueOptions.find((opt) => opt.id === selectedValues[0]);\n\n return option?.label || selectedValues[0];\n }\n\n return `${selectedValues.length} selected`;\n };\n\n return {\n getSelectedValues,\n isValueSelected,\n getDisplayValue,\n };\n};\n","import React, { useRef } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\n\ninterface CustomValueInputProps {\n inputValue: string;\n setInputValue: (value: string) => void;\n customValuePlaceholder: string;\n customValueButtonLabel: string;\n onSubmit: () => void;\n handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => void;\n}\n\nexport const CustomValueInput: React.FC<CustomValueInputProps> = ({\n inputValue,\n setInputValue,\n customValuePlaceholder,\n customValueButtonLabel,\n onSubmit,\n handleKeyDown,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder={customValuePlaceholder}\n className=\"mb-2\"\n onKeyDown={(e) => handleKeyDown(e, true)}\n />\n <Button\n type=\"submit\"\n variant=\"dark\"\n className=\"w-full\"\n onKeyDown={(e) => handleKeyDown(e, false)}\n data-custom-submit-button\n >\n {customValueButtonLabel}\n </Button>\n </form>\n );\n};\n","import React, { useState, useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterValue, FilterOption } from '../types';\n\nimport { Button } from '@/components/ui/button';\n\ninterface MultiSelectDropdownProps {\n internalFilter: FilterValue;\n valueOptions: FilterOption[];\n onConfirm: (selectedValues: string[]) => void;\n onClose: () => void;\n}\n\nconst getInitialValues = (value: FilterValue['value']): string[] => {\n if (Array.isArray(value)) {\n return value;\n } else if (value) {\n return [value];\n }\n\n return [];\n};\n\nexport const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({\n internalFilter,\n valueOptions,\n onConfirm,\n onClose,\n}) => {\n const [pendingValues, setPendingValues] = useState<string[]>(() => getInitialValues(internalFilter.value));\n const [announcement, setAnnouncement] = useState<string>('');\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n\n const handleValueToggle = (valueId: string) => {\n const option = valueOptions.find((opt) => opt.id === valueId);\n const isCurrentlySelected = pendingValues.includes(valueId);\n\n setPendingValues((prev) => {\n const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];\n\n // Announce the change\n if (option) {\n const action = isCurrentlySelected ? 'deselected' : 'selected';\n setAnnouncement(`${option.label} ${action}.`);\n }\n\n return newValues;\n });\n };\n\n const handleConfirm = () => {\n onConfirm(pendingValues);\n onClose();\n };\n\n const isValueSelected = (valueId: string): boolean => {\n return pendingValues.includes(valueId);\n };\n\n const focusButton = (index: number) => {\n if (index < valueOptions.length) {\n buttonRefs.current[index]?.focus();\n } else {\n applyButtonRef.current?.focus();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n if (index < valueOptions.length) {\n // If the user is selecting an option\n handleValueToggle(valueOptions[index].id);\n } else {\n // If the user is selecting the apply button\n handleConfirm();\n }\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\" aria-multiselectable=\"true\">\n {/* Screen reader announcements */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => handleValueToggle(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n role=\"option\"\n aria-selected={isValueSelected(option.id)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n\n <div className=\"border-t border-border mt-1 pt-2 px-2 pb-2\">\n <Button\n ref={applyButtonRef}\n onClick={handleConfirm}\n size=\"sm\"\n className=\"w-full\"\n disabled={pendingValues.length === 0}\n onKeyDown={(e) => handleKeyDown(e, valueOptions.length)}\n >\n Apply ({pendingValues.length} selected)\n </Button>\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterOption } from '../types';\n\ninterface SingleSelectDropdownProps {\n valueOptions: FilterOption[];\n isValueSelected: (valueId: string) => boolean;\n onValueSelect: (valueId: string) => void;\n}\n\nexport const SingleSelectDropdown: React.FC<SingleSelectDropdownProps> = ({\n valueOptions,\n isValueSelected,\n onValueSelect,\n}) => {\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const focusButton = (index: number) => {\n buttonRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length - 1);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n onValueSelect(valueOptions[index].id);\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\">\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => onValueSelect(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n </div>\n );\n};\n","import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { FilterProps, FilterValue, Operator } from './types';\nimport { useMultiSelectHelpers } from './hooks';\nimport { CustomValueInput } from './components/CustomValueInput';\nimport { MultiSelectDropdown } from './components/MultiSelectDropdown';\nimport { SingleSelectDropdown } from './components/SingleSelectDropdown';\n\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nconst Filter = forwardRef<{ focus: () => void }, FilterProps>(\n (\n {\n filter,\n sourceOptions,\n rules,\n onSourceChange,\n onRemoveFilter,\n onFilterChange,\n selectPlaceholder = 'Select a value',\n customValuePlaceholder = 'Enter custom value',\n customValueButtonLabel = 'Done',\n sourceFirstMessage = 'Please select a source first',\n }: FilterProps,\n ref,\n ) => {\n // State\n const [internalFilter, setInternalFilter] = useState<FilterValue>({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n const [inputValue, setInputValue] = useState('');\n const [openDropdownType, setOpenDropdownType] = useState<'source' | 'operator' | 'value' | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const sourceButtonRef = useRef<HTMLButtonElement>(null);\n const divRef = useRef<HTMLDivElement>(null);\n\n // Expose focus method\n useImperativeHandle(ref, () => ({\n focus: () => {\n sourceButtonRef.current?.focus();\n },\n }));\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n const isMultiSelect = currentRules?.multiSelect || false;\n let inputType = currentRules?.inputType || 'dropdown';\n if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {\n inputType = 'custom';\n }\n const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];\n\n // Multi-select helpers\n const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(\n internalFilter,\n valueOptions,\n selectPlaceholder,\n );\n\n // Auto-focus input when dropdown opens and custom input is needed\n useEffect(() => {\n if (openDropdownType === 'value' && inputType === 'custom') {\n const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);\n\n return () => clearTimeout(timeoutId);\n }\n\n return undefined;\n }, [openDropdownType, inputType]);\n\n // Sync with external state\n useEffect(() => {\n setInternalFilter({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n }, [filter]);\n\n // Helper function to check if filter is complete and trigger onChange\n const checkAndTriggerChange = (newFilter: FilterValue) => {\n const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();\n\n const isComplete = newFilter.source && newFilter.operator && hasValue;\n\n if (isComplete) {\n onFilterChange(newFilter);\n }\n };\n\n // Handle field updates\n const updateFilterField = (field: keyof FilterValue, value: string) => {\n const newFilter: FilterValue = { ...internalFilter, [field]: value };\n\n // Special handling for source changes\n if (field === 'source') {\n const sourceRules = rules[value];\n newFilter.operator = sourceRules?.operators[0]?.id as Operator;\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n // If operator changes, also clear value if inputType is dropdown\n if (field === 'operator') {\n if (internalFilter.source) {\n const sourceRules = rules[internalFilter.source];\n if (sourceRules?.inputType === 'dropdown') {\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n if (!isMultiSelect || field !== 'value') {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select value changes\n const handleValueToggle = (valueId: string) => {\n const selectedValues = getSelectedValues();\n let newValues: string[];\n\n if (isMultiSelect) {\n if (selectedValues.includes(valueId)) {\n newValues = selectedValues.filter((id) => id !== valueId);\n } else {\n newValues = [...selectedValues, valueId];\n }\n } else {\n newValues = [valueId];\n }\n\n const newFilter = {\n ...internalFilter,\n value: isMultiSelect ? newValues : newValues[0] || '',\n };\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n // Close dropdown for single select, keep open for multi-select\n if (!isMultiSelect) {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select confirmation\n const handleMultiSelectConfirm = (selectedValues: string[]) => {\n const newFilter = {\n ...internalFilter,\n value: selectedValues,\n };\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;\n if (isComplete) onFilterChange(newFilter);\n\n setOpenDropdownType(null);\n };\n\n // Handle custom value submission\n const handleCustomValueSubmit = () => {\n if (inputValue.trim()) {\n const newFilter = { ...internalFilter, value: inputValue.trim() };\n setInternalFilter(newFilter);\n setInputValue('');\n setOpenDropdownType(null);\n if (newFilter.source && newFilter.operator && newFilter.value) {\n onFilterChange(newFilter);\n }\n }\n };\n\n // Tab trap handlers\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => {\n if (e.key === 'Escape') {\n setOpenDropdownType(null);\n\n return;\n }\n if (e.key === 'Tab') {\n if (isInput && !e.shiftKey) {\n e.preventDefault();\n const button = document.querySelector('[data-custom-submit-button]') as HTMLButtonElement;\n button?.focus();\n } else if (!isInput) {\n e.preventDefault();\n inputRef.current?.focus();\n }\n }\n };\n\n return (\n <ButtonGroup\n ref={divRef}\n orientation=\"horizontal\"\n className=\"rounded-full border border-border divide-x-2 divide-dark-500\"\n >\n {/* Source Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'source'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'source' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button ref={sourceButtonRef} variant=\"ghost\" size=\"xs\" className=\"rounded-l-full font-bold\">\n {sourceOptions.find((opt) => opt.id === internalFilter.source)?.label ||\n sourceOptions[0]?.label ||\n selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {sourceOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => {\n updateFilterField('source', option.id);\n onSourceChange?.(option.id);\n }}\n >\n {option.id === internalFilter.source && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Operator Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'operator'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'operator' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\">\n {operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {operatorOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('operator', option.id)}\n >\n {option.id === internalFilter.operator && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Value Popover */}\n <Popover\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n >\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\" className=\"font-bold\">\n {getDisplayValue()}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-0\">\n {inputType === 'custom' && (\n <div className=\"p-3\">\n <CustomValueInput\n inputValue={inputValue}\n setInputValue={setInputValue}\n customValuePlaceholder={customValuePlaceholder}\n customValueButtonLabel={customValueButtonLabel}\n onSubmit={handleCustomValueSubmit}\n handleKeyDown={handleKeyDown}\n />\n </div>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n <>\n {isMultiSelect ? (\n <MultiSelectDropdown\n internalFilter={internalFilter}\n valueOptions={valueOptions}\n onConfirm={handleMultiSelectConfirm}\n onClose={() => setOpenDropdownType(null)}\n />\n ) : (\n <SingleSelectDropdown\n valueOptions={valueOptions}\n isValueSelected={isValueSelected}\n onValueSelect={handleValueToggle}\n />\n )}\n </>\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n setInternalFilter({ id: filter.id });\n setOpenDropdownType(null);\n onRemoveFilter(filter.id);\n }}\n className=\"p-2 hover:bg-black/10 rounded-none rounded-r-full\"\n aria-label=\"Remove filter\"\n >\n <XCircle size={16} weight=\"fill\" />\n </Button>\n </ButtonGroup>\n );\n },\n);\n\nFilter.displayName = 'Filter';\n\nexport { Filter };\n","import React, { useState, useEffect, useRef } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './index';\nimport { Button } from '../ui/button';\n\nimport { cn } from '@/lib/utils';\n\ninterface FiltersProps extends React.HTMLAttributes<HTMLDivElement> {\n filters: FilterValue[];\n onFilterChange: (filter: FilterValue) => void;\n onFilterRemove: (filterId: string | number) => void;\n onFilterAdd?: (filter: FilterValue) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({\n filters,\n onFilterChange,\n onFilterRemove,\n onFilterAdd,\n sourceOptions,\n rules,\n className,\n}: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n const filterRefs = useRef<{ [key: string]: { focus: () => void } | null }>({});\n\n // Sync internal state with props\n useEffect(() => {\n setInternalFilters(filters || []);\n }, [filters]);\n\n // Get sources that are already in use\n const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);\n\n // Get available sources that haven't been used yet\n const availableSources = sourceOptions.filter((option) => {\n // If the source has multiSelect enabled, filter out used sources\n if (rules[option.id]?.multiSelect) {\n return !usedSources.includes(option.id);\n }\n\n // If multiSelect is false or undefined, allow the source to be used multiple times\n return sourceOptions;\n });\n\n // Check if we can add more filters\n const canAddFilter = availableSources.length > 0;\n\n const handleAddFilter = () => {\n if (!canAddFilter) return;\n\n const newFilter = {\n id: createId(),\n source: availableSources[0].id,\n operator: Operator.IS,\n value: rules[availableSources[0].id]?.multiSelect ? [] : '',\n };\n\n const newFilters = [...internalFilters, newFilter];\n setInternalFilters(newFilters);\n\n // Focus the new filter after it's rendered\n requestAnimationFrame(() => {\n filterRefs.current[newFilter.id]?.focus();\n });\n\n // Notify parent if callback provided\n onFilterAdd?.(newFilter);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n const newFilters = internalFilters.filter((f) => f.id !== filter.id);\n setInternalFilters(newFilters);\n onFilterRemove(filter.id);\n };\n\n return (\n <fieldset className={cn('flex flex-wrap gap-2', className)}>\n <legend className=\"sr-only\">Filters</legend>\n {internalFilters?.map((filter) => {\n // For each filter, include available sources plus its own current source\n const filterSourceOptions = sourceOptions.filter(\n (option) =>\n !usedSources.includes(option.id) || // Available sources\n option.id === filter.source, // Or its own current source\n );\n\n return (\n <Filter\n key={filter.id}\n ref={(ref) => {\n filterRefs.current[filter.id] = ref;\n }}\n filter={filter}\n sourceOptions={filterSourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n );\n })}\n {canAddFilter && (\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n title=\"Add filter\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n )}\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","React"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { Check, SpinnerGap } from '@phosphor-icons/react';
|
|
3
3
|
import { c as cn } from './utils.Cwtlq8dh.js';
|
|
4
4
|
import { CommandItem } from '../components/ui/command.js';
|
|
5
|
-
import { C as Combobox } from './combobox.
|
|
5
|
+
import { C as Combobox } from './combobox.BpGnNZ6a.js';
|
|
6
6
|
|
|
7
7
|
const FONT_CACHE_KEY = "brainfish-google-fonts-cache";
|
|
8
8
|
const FONT_CACHE_TIMESTAMP_KEY = "brainfish-google-fonts-cache-timestamp";
|
|
@@ -178,4 +178,4 @@ function FontPicker({
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
export { FontPicker as F, FontPickerItem as a, clearFontCache as c, getCachedFonts as g, loadFont as l, setCachedFonts as s, useFontOptions as u };
|
|
181
|
-
//# sourceMappingURL=font-picker.
|
|
181
|
+
//# sourceMappingURL=font-picker.CtGg-OWt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"font-picker.DX1mER3H.js","sources":["../../../src/components/font-picker/font-utils.ts","../../../src/components/font-picker/use-font-options.ts","../../../src/components/font-picker/font-picker-item.tsx","../../../src/components/font-picker/font-picker.tsx"],"sourcesContent":["import { FontOption } from './types';\n\n// Cache keys for localStorage\nconst FONT_CACHE_KEY = 'brainfish-google-fonts-cache';\nconst FONT_CACHE_TIMESTAMP_KEY = 'brainfish-google-fonts-cache-timestamp';\nconst FONT_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// Cache for loaded font stylesheets to prevent duplicate loads\nconst loadedFonts = new Set<string>();\n\n/**\n * Get cached fonts from localStorage\n */\nexport const getCachedFonts = (): FontOption[] | null => {\n try {\n const timestamp = localStorage.getItem(FONT_CACHE_TIMESTAMP_KEY);\n if (!timestamp) return null;\n\n const cacheAge = Date.now() - parseInt(timestamp, 10);\n if (cacheAge > FONT_CACHE_DURATION_MS) {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n\n return null;\n }\n\n const cached = localStorage.getItem(FONT_CACHE_KEY);\n if (!cached) return null;\n\n return JSON.parse(cached) as FontOption[];\n } catch {\n return null;\n }\n};\n\n/**\n * Save fonts to localStorage cache\n */\nexport const setCachedFonts = (fonts: FontOption[]): void => {\n try {\n localStorage.setItem(FONT_CACHE_KEY, JSON.stringify(fonts));\n localStorage.setItem(FONT_CACHE_TIMESTAMP_KEY, Date.now().toString());\n } catch {\n // localStorage might be full or unavailable, ignore\n }\n};\n\n/**\n * Load a Google Font stylesheet dynamically\n */\nexport const loadFont = (fontFamily: string): void => {\n if (loadedFonts.has(fontFamily)) return;\n\n const link = document.createElement('link');\n link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(/ /g, '+')}&display=swap`;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n loadedFonts.add(fontFamily);\n};\n\n/**\n * Clear the font cache from localStorage\n * Useful for forcing a fresh fetch of fonts\n */\nexport const clearFontCache = (): void => {\n try {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n } catch {\n // localStorage might be unavailable, ignore\n }\n};\n","import * as React from 'react';\n\nimport { FontOption } from './types';\nimport { getCachedFonts, setCachedFonts, loadFont } from './font-utils';\n\nexport interface UseFontOptionsProps {\n apiKey: string;\n maxFonts?: number;\n onError?: (error: Error) => void;\n}\n\nexport interface UseFontOptionsReturn {\n fonts: FontOption[];\n isLoading: boolean;\n loadFont: typeof loadFont;\n}\n\n/**\n * Hook to fetch and manage Google Fonts options\n * Handles caching, loading state, and font stylesheet loading\n */\nexport function useFontOptions({ apiKey, maxFonts = 500, onError }: UseFontOptionsProps): UseFontOptionsReturn {\n const [fonts, setFonts] = React.useState<FontOption[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n\n // Stabilize onError callback reference to prevent effect re-runs when\n // consumers pass inline functions (which create new references on every render)\n const onErrorRef = React.useRef(onError);\n React.useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n React.useEffect(() => {\n const fetchFonts = async () => {\n // Check cache first\n const cachedFonts = getCachedFonts();\n if (cachedFonts && cachedFonts.length > 0) {\n setFonts(cachedFonts.slice(0, maxFonts));\n setIsLoading(false);\n\n return;\n }\n\n try {\n const response = await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${apiKey}&sort=popularity`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fonts: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n const fontOptions: FontOption[] = data.items.map((fontItem: { family: string; category: string; variants: string[] }) => ({\n value: fontItem.family,\n label: fontItem.family,\n category: fontItem.category,\n variants: fontItem.variants,\n }));\n\n // Cache all fonts, but only display up to maxFonts\n setCachedFonts(fontOptions);\n setFonts(fontOptions.slice(0, maxFonts));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch fonts');\n\n console.error('FontPicker: Failed to fetch Google Fonts', error);\n onErrorRef.current?.(error);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetchFonts();\n }, [apiKey, maxFonts]);\n\n return { fonts, isLoading, loadFont };\n}\n","import * as React from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FontOption } from './types';\nimport { loadFont } from './font-utils';\n\nimport { cn } from '@/lib/utils';\nimport { CommandItem } from '@/components/ui/command';\n\nexport interface FontPickerItemProps {\n font: FontOption;\n isSelected: boolean;\n onSelect: () => void;\n}\n\n/**\n * Individual font item in the dropdown list\n * Loads font on mount for preview using Intersection Observer\n * Memoized to prevent unnecessary re-renders\n */\nexport const FontPickerItem = React.memo(function FontPickerItem({ font, isSelected, onSelect }: FontPickerItemProps) {\n const itemRef = React.useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = React.useState(false);\n\n // Use Intersection Observer to lazy-load fonts\n React.useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n { threshold: 0.1 },\n );\n\n if (itemRef.current) {\n observer.observe(itemRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n // Load font when visible\n React.useEffect(() => {\n if (isVisible) {\n loadFont(font.value);\n }\n }, [isVisible, font.value]);\n\n // Build accessible label\n const ariaLabel = `Select ${font.label} font${font.category ? `, ${font.category} category` : ''}`;\n\n return (\n <CommandItem\n ref={itemRef}\n value={font.label}\n onSelect={onSelect}\n className=\"cursor-pointer\"\n aria-label={ariaLabel}\n aria-selected={isSelected}\n >\n <span style={{ fontFamily: isVisible ? font.value : undefined }} className=\"flex-1 truncate\">\n {font.label}\n </span>\n {font.category && <span className=\"text-xs text-muted-foreground capitalize\">{font.category}</span>}\n <Check className={cn('ml-2 h-4 w-4', isSelected ? 'opacity-100' : 'opacity-0')} />\n </CommandItem>\n );\n});\n","import * as React from 'react';\nimport { SpinnerGap } from '@phosphor-icons/react';\n\nimport { useFontOptions } from './use-font-options';\nimport { FontPickerItem } from './font-picker-item';\n\nimport { Combobox } from '@/components/combobox/combobox';\n\nexport interface FontPickerProps {\n /** Currently selected font family */\n value?: string;\n /** Callback when font selection changes */\n onChange?: (fontFamily: string) => void;\n /** Google Fonts API key (required) */\n apiKey: string;\n /** Placeholder text when no font is selected */\n placeholder?: string;\n /** Text shown in search input */\n searchPlaceholder?: string;\n /** Text shown when no fonts match the search */\n noResultsText?: string;\n /** Text shown while fonts are loading */\n loadingText?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Additional CSS classes for the trigger button */\n className?: string;\n /** Width of the dropdown (defaults to trigger width) */\n dropdownWidth?: number;\n /** Maximum number of fonts to display (for performance) */\n maxFonts?: number;\n /** Callback when an error occurs fetching fonts */\n onError?: (error: Error) => void;\n}\n\n/**\n * FontPicker - A searchable dropdown for selecting Google Fonts\n *\n * @example\n * ```tsx\n * const [font, setFont] = useState('Inter');\n *\n * <FontPicker\n * apiKey=\"YOUR_API_KEY\"\n * value={font}\n * onChange={setFont}\n * placeholder=\"Select a font\"\n * />\n * ```\n */\nexport function FontPicker({\n value,\n onChange,\n apiKey,\n placeholder = 'Select a font...',\n searchPlaceholder = 'Search fonts...',\n noResultsText = 'No fonts found.',\n loadingText = 'Loading fonts...',\n disabled = false,\n className,\n dropdownWidth,\n maxFonts = 500,\n onError,\n}: FontPickerProps) {\n const { fonts, isLoading, loadFont } = useFontOptions({ apiKey, maxFonts, onError });\n\n // Load font stylesheet when selected\n React.useEffect(() => {\n if (value) {\n loadFont(value);\n }\n }, [value, loadFont]);\n\n // fonts already have value/label which Combobox requires\n const options = fonts;\n\n return (\n <Combobox\n options={options}\n value={value}\n onChange={onChange}\n defaultValueLabel={placeholder}\n placeholder={searchPlaceholder}\n noResultsLabel={noResultsText}\n disabled={disabled || isLoading}\n className={className}\n dropdownWidth={dropdownWidth}\n renderTrigger={({ selectedItem }) => {\n if (isLoading) {\n return (\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <SpinnerGap className=\"h-4 w-4 animate-spin\" />\n {loadingText}\n </span>\n );\n }\n\n if (selectedItem) {\n return <span style={{ fontFamily: selectedItem.value }}>{selectedItem.label}</span>;\n }\n\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }}\n renderItem={({ item, isSelected, onSelect }) => (\n <FontPickerItem font={item} isSelected={isSelected} onSelect={onSelect} />\n )}\n />\n );\n}\n\nexport default FontPicker;\n"],"names":["FontPickerItem"],"mappings":";;;;;;AAGA,MAAM,cAAA,GAAiB,8BAAA;AACvB,MAAM,wBAAA,GAA2B,wCAAA;AACjC,MAAM,sBAAA,GAAyB,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAG9C,MAAM,WAAA,uBAAkB,GAAA,EAAY;AAK7B,MAAM,iBAAiB,MAA2B;AACvD,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,YAAA,CAAa,OAAA,CAAQ,wBAAwB,CAAA;AAC/D,IAAA,IAAI,CAAC,WAAW,OAAO,IAAA;AAEvB,IAAA,MAAM,WAAW,IAAA,CAAK,GAAA,EAAI,GAAI,QAAA,CAAS,WAAW,EAAE,CAAA;AACpD,IAAA,IAAI,WAAW,sBAAA,EAAwB;AACrC,MAAA,YAAA,CAAa,WAAW,cAAc,CAAA;AACtC,MAAA,YAAA,CAAa,WAAW,wBAAwB,CAAA;AAEhD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,cAAc,CAAA;AAClD,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,IAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKO,MAAM,cAAA,GAAiB,CAAC,KAAA,KAA8B;AAC3D,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,OAAA,CAAQ,cAAA,EAAgB,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAC1D,IAAA,YAAA,CAAa,QAAQ,wBAAA,EAA0B,IAAA,CAAK,GAAA,EAAI,CAAE,UAAU,CAAA;AAAA,EACtE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAKO,MAAM,QAAA,GAAW,CAAC,UAAA,KAA6B;AACpD,EAAA,IAAI,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA,EAAG;AAEjC,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC1C,EAAA,IAAA,CAAK,OAAO,CAAA,yCAAA,EAA4C,UAAA,CAAW,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA,aAAA,CAAA;AACrF,EAAA,IAAA,CAAK,GAAA,GAAM,YAAA;AACX,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAC9B,EAAA,WAAA,CAAY,IAAI,UAAU,CAAA;AAC5B;AAMO,MAAM,iBAAiB,MAAY;AACxC,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,WAAW,cAAc,CAAA;AACtC,IAAA,YAAA,CAAa,WAAW,wBAAwB,CAAA;AAAA,EAClD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;AClDO,SAAS,eAAe,EAAE,MAAA,EAAQ,QAAA,GAAW,GAAA,EAAK,SAAQ,EAA8C;AAC7G,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAI,KAAA,CAAM,QAAA,CAAuB,EAAE,CAAA;AACzD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,KAAA,CAAM,SAAS,IAAI,CAAA;AAIrD,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA;AACvC,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAAA,EACvB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,aAAa,YAAY;AAE7B,MAAA,MAAM,cAAc,cAAA,EAAe;AACnC,MAAA,IAAI,WAAA,IAAe,WAAA,CAAY,MAAA,GAAS,CAAA,EAAG;AACzC,QAAA,QAAA,CAAS,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAC,CAAA;AACvC,QAAA,YAAA,CAAa,KAAK,CAAA;AAElB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,oDAAA,EAAuD,MAAM,CAAA,gBAAA,CAAkB,CAAA;AAE5G,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,QACjE;AAEA,QAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,QAAA,MAAM,WAAA,GAA4B,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,QAAA,MAAwE;AAAA,UACxH,OAAO,QAAA,CAAS,MAAA;AAAA,UAChB,OAAO,QAAA,CAAS,MAAA;AAAA,UAChB,UAAU,QAAA,CAAS,QAAA;AAAA,UACnB,UAAU,QAAA,CAAS;AAAA,SACrB,CAAE,CAAA;AAGF,QAAA,cAAA,CAAe,WAAW,CAAA;AAC1B,QAAA,QAAA,CAAS,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAC,CAAA;AAAA,MACzC,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,QAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,MAAM,uBAAuB,CAAA;AAE5E,QAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,KAAK,CAAA;AAC/D,QAAA,UAAA,CAAW,UAAU,KAAK,CAAA;AAAA,MAC5B,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAEA,IAAA,KAAK,UAAA,EAAW;AAAA,EAClB,CAAA,EAAG,CAAC,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAErB,EAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAS;AACtC;;ACxDO,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,SAASA,gBAAe,EAAE,IAAA,EAAM,UAAA,EAAY,QAAA,EAAS,EAAwB;AACpH,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,MAAA,CAAuB,IAAI,CAAA;AACjD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,KAAA,CAAM,SAAS,KAAK,CAAA;AAGtD,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,WAAW,IAAI,oBAAA;AAAA,MACnB,CAAC,CAAC,KAAK,CAAA,KAAM;AACX,QAAA,IAAI,MAAM,cAAA,EAAgB;AACxB,UAAA,YAAA,CAAa,IAAI,CAAA;AACjB,UAAA,QAAA,CAAS,UAAA,EAAW;AAAA,QACtB;AAAA,MACF,CAAA;AAAA,MACA,EAAE,WAAW,GAAA;AAAI,KACnB;AAEA,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,QAAA,CAAS,OAAA,CAAQ,QAAQ,OAAO,CAAA;AAAA,IAClC;AAEA,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA,IACrB;AAAA,EACF,CAAA,EAAG,CAAC,SAAA,EAAW,IAAA,CAAK,KAAK,CAAC,CAAA;AAG1B,EAAA,MAAM,SAAA,GAAY,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,KAAA,EAAQ,IAAA,CAAK,QAAA,GAAW,CAAA,EAAA,EAAK,IAAA,CAAK,QAAQ,CAAA,SAAA,CAAA,GAAc,EAAE,CAAA,CAAA;AAEhG,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,OAAA;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAA;AAAA,MACA,SAAA,EAAU,gBAAA;AAAA,MACV,YAAA,EAAY,SAAA;AAAA,MACZ,eAAA,EAAe;AAAA,KAAA;AAAA,oBAEf,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,UAAA,EAAY,SAAA,GAAY,IAAA,CAAK,KAAA,GAAQ,MAAA,EAAU,EAAG,SAAA,EAAU,iBAAA,EAAA,EACxE,KAAK,KACR,CAAA;AAAA,IACC,KAAK,QAAA,oBAAY,KAAA,CAAA,aAAA,CAAC,UAAK,SAAA,EAAU,0CAAA,EAAA,EAA4C,KAAK,QAAS,CAAA;AAAA,oBAC5F,KAAA,CAAA,aAAA,CAAC,SAAM,SAAA,EAAW,EAAA,CAAG,gBAAgB,UAAA,GAAa,aAAA,GAAgB,WAAW,CAAA,EAAG;AAAA,GAClF;AAEJ,CAAC;;ACnBM,SAAS,UAAA,CAAW;AAAA,EACzB,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA,GAAc,kBAAA;AAAA,EACd,iBAAA,GAAoB,iBAAA;AAAA,EACpB,aAAA,GAAgB,iBAAA;AAAA,EAChB,WAAA,GAAc,kBAAA;AAAA,EACd,QAAA,GAAW,KAAA;AAAA,EACX,SAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA,GAAW,GAAA;AAAA,EACX;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAS,GAAI,eAAe,EAAE,MAAA,EAAQ,QAAA,EAAU,OAAA,EAAS,CAAA;AAGnF,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,QAAA,CAAS,KAAK,CAAA;AAAA,IAChB;AAAA,EACF,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAGpB,EAAA,MAAM,OAAA,GAAU,KAAA;AAEhB,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,iBAAA,EAAmB,WAAA;AAAA,MACnB,WAAA,EAAa,iBAAA;AAAA,MACb,cAAA,EAAgB,aAAA;AAAA,MAChB,UAAU,QAAA,IAAY,SAAA;AAAA,MACtB,SAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA,EAAe,CAAC,EAAE,YAAA,EAAa,KAAM;AACnC,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,uBACE,KAAA,CAAA,aAAA,CAAC,UAAK,SAAA,EAAU,+CAAA,EAAA,sCACb,UAAA,EAAA,EAAW,SAAA,EAAU,sBAAA,EAAuB,CAAA,EAC5C,WACH,CAAA;AAAA,QAEJ;AAEA,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,uBAAO,KAAA,CAAA,aAAA,CAAC,UAAK,KAAA,EAAO,EAAE,YAAY,YAAA,CAAa,KAAA,EAAM,EAAA,EAAI,YAAA,CAAa,KAAM,CAAA;AAAA,QAC9E;AAEA,QAAA,uBAAO,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAA,EAAyB,WAAY,CAAA;AAAA,MAC9D,CAAA;AAAA,MACA,UAAA,EAAY,CAAC,EAAE,IAAA,EAAM,UAAA,EAAY,QAAA,EAAS,qBACxC,KAAA,CAAA,aAAA,CAAC,cAAA,EAAA,EAAe,IAAA,EAAM,IAAA,EAAM,UAAA,EAAwB,QAAA,EAAoB;AAAA;AAAA,GAE5E;AAEJ;;;;"}
|
|
1
|
+
{"version":3,"file":"font-picker.CtGg-OWt.js","sources":["../../../src/components/font-picker/font-utils.ts","../../../src/components/font-picker/use-font-options.ts","../../../src/components/font-picker/font-picker-item.tsx","../../../src/components/font-picker/font-picker.tsx"],"sourcesContent":["import { FontOption } from './types';\n\n// Cache keys for localStorage\nconst FONT_CACHE_KEY = 'brainfish-google-fonts-cache';\nconst FONT_CACHE_TIMESTAMP_KEY = 'brainfish-google-fonts-cache-timestamp';\nconst FONT_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// Cache for loaded font stylesheets to prevent duplicate loads\nconst loadedFonts = new Set<string>();\n\n/**\n * Get cached fonts from localStorage\n */\nexport const getCachedFonts = (): FontOption[] | null => {\n try {\n const timestamp = localStorage.getItem(FONT_CACHE_TIMESTAMP_KEY);\n if (!timestamp) return null;\n\n const cacheAge = Date.now() - parseInt(timestamp, 10);\n if (cacheAge > FONT_CACHE_DURATION_MS) {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n\n return null;\n }\n\n const cached = localStorage.getItem(FONT_CACHE_KEY);\n if (!cached) return null;\n\n return JSON.parse(cached) as FontOption[];\n } catch {\n return null;\n }\n};\n\n/**\n * Save fonts to localStorage cache\n */\nexport const setCachedFonts = (fonts: FontOption[]): void => {\n try {\n localStorage.setItem(FONT_CACHE_KEY, JSON.stringify(fonts));\n localStorage.setItem(FONT_CACHE_TIMESTAMP_KEY, Date.now().toString());\n } catch {\n // localStorage might be full or unavailable, ignore\n }\n};\n\n/**\n * Load a Google Font stylesheet dynamically\n */\nexport const loadFont = (fontFamily: string): void => {\n if (loadedFonts.has(fontFamily)) return;\n\n const link = document.createElement('link');\n link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(/ /g, '+')}&display=swap`;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n loadedFonts.add(fontFamily);\n};\n\n/**\n * Clear the font cache from localStorage\n * Useful for forcing a fresh fetch of fonts\n */\nexport const clearFontCache = (): void => {\n try {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n } catch {\n // localStorage might be unavailable, ignore\n }\n};\n","import * as React from 'react';\n\nimport { FontOption } from './types';\nimport { getCachedFonts, setCachedFonts, loadFont } from './font-utils';\n\nexport interface UseFontOptionsProps {\n apiKey: string;\n maxFonts?: number;\n onError?: (error: Error) => void;\n}\n\nexport interface UseFontOptionsReturn {\n fonts: FontOption[];\n isLoading: boolean;\n loadFont: typeof loadFont;\n}\n\n/**\n * Hook to fetch and manage Google Fonts options\n * Handles caching, loading state, and font stylesheet loading\n */\nexport function useFontOptions({ apiKey, maxFonts = 500, onError }: UseFontOptionsProps): UseFontOptionsReturn {\n const [fonts, setFonts] = React.useState<FontOption[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n\n // Stabilize onError callback reference to prevent effect re-runs when\n // consumers pass inline functions (which create new references on every render)\n const onErrorRef = React.useRef(onError);\n React.useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n React.useEffect(() => {\n const fetchFonts = async () => {\n // Check cache first\n const cachedFonts = getCachedFonts();\n if (cachedFonts && cachedFonts.length > 0) {\n setFonts(cachedFonts.slice(0, maxFonts));\n setIsLoading(false);\n\n return;\n }\n\n try {\n const response = await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${apiKey}&sort=popularity`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fonts: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n const fontOptions: FontOption[] = data.items.map((fontItem: { family: string; category: string; variants: string[] }) => ({\n value: fontItem.family,\n label: fontItem.family,\n category: fontItem.category,\n variants: fontItem.variants,\n }));\n\n // Cache all fonts, but only display up to maxFonts\n setCachedFonts(fontOptions);\n setFonts(fontOptions.slice(0, maxFonts));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch fonts');\n\n console.error('FontPicker: Failed to fetch Google Fonts', error);\n onErrorRef.current?.(error);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetchFonts();\n }, [apiKey, maxFonts]);\n\n return { fonts, isLoading, loadFont };\n}\n","import * as React from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FontOption } from './types';\nimport { loadFont } from './font-utils';\n\nimport { cn } from '@/lib/utils';\nimport { CommandItem } from '@/components/ui/command';\n\nexport interface FontPickerItemProps {\n font: FontOption;\n isSelected: boolean;\n onSelect: () => void;\n}\n\n/**\n * Individual font item in the dropdown list\n * Loads font on mount for preview using Intersection Observer\n * Memoized to prevent unnecessary re-renders\n */\nexport const FontPickerItem = React.memo(function FontPickerItem({ font, isSelected, onSelect }: FontPickerItemProps) {\n const itemRef = React.useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = React.useState(false);\n\n // Use Intersection Observer to lazy-load fonts\n React.useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n { threshold: 0.1 },\n );\n\n if (itemRef.current) {\n observer.observe(itemRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n // Load font when visible\n React.useEffect(() => {\n if (isVisible) {\n loadFont(font.value);\n }\n }, [isVisible, font.value]);\n\n // Build accessible label\n const ariaLabel = `Select ${font.label} font${font.category ? `, ${font.category} category` : ''}`;\n\n return (\n <CommandItem\n ref={itemRef}\n value={font.label}\n onSelect={onSelect}\n className=\"cursor-pointer\"\n aria-label={ariaLabel}\n aria-selected={isSelected}\n >\n <span style={{ fontFamily: isVisible ? font.value : undefined }} className=\"flex-1 truncate\">\n {font.label}\n </span>\n {font.category && <span className=\"text-xs text-muted-foreground capitalize\">{font.category}</span>}\n <Check className={cn('ml-2 h-4 w-4', isSelected ? 'opacity-100' : 'opacity-0')} />\n </CommandItem>\n );\n});\n","import * as React from 'react';\nimport { SpinnerGap } from '@phosphor-icons/react';\n\nimport { useFontOptions } from './use-font-options';\nimport { FontPickerItem } from './font-picker-item';\n\nimport { Combobox } from '@/components/combobox/combobox';\n\nexport interface FontPickerProps {\n /** Currently selected font family */\n value?: string;\n /** Callback when font selection changes */\n onChange?: (fontFamily: string) => void;\n /** Google Fonts API key (required) */\n apiKey: string;\n /** Placeholder text when no font is selected */\n placeholder?: string;\n /** Text shown in search input */\n searchPlaceholder?: string;\n /** Text shown when no fonts match the search */\n noResultsText?: string;\n /** Text shown while fonts are loading */\n loadingText?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Additional CSS classes for the trigger button */\n className?: string;\n /** Width of the dropdown (defaults to trigger width) */\n dropdownWidth?: number;\n /** Maximum number of fonts to display (for performance) */\n maxFonts?: number;\n /** Callback when an error occurs fetching fonts */\n onError?: (error: Error) => void;\n}\n\n/**\n * FontPicker - A searchable dropdown for selecting Google Fonts\n *\n * @example\n * ```tsx\n * const [font, setFont] = useState('Inter');\n *\n * <FontPicker\n * apiKey=\"YOUR_API_KEY\"\n * value={font}\n * onChange={setFont}\n * placeholder=\"Select a font\"\n * />\n * ```\n */\nexport function FontPicker({\n value,\n onChange,\n apiKey,\n placeholder = 'Select a font...',\n searchPlaceholder = 'Search fonts...',\n noResultsText = 'No fonts found.',\n loadingText = 'Loading fonts...',\n disabled = false,\n className,\n dropdownWidth,\n maxFonts = 500,\n onError,\n}: FontPickerProps) {\n const { fonts, isLoading, loadFont } = useFontOptions({ apiKey, maxFonts, onError });\n\n // Load font stylesheet when selected\n React.useEffect(() => {\n if (value) {\n loadFont(value);\n }\n }, [value, loadFont]);\n\n // fonts already have value/label which Combobox requires\n const options = fonts;\n\n return (\n <Combobox\n options={options}\n value={value}\n onChange={onChange}\n defaultValueLabel={placeholder}\n placeholder={searchPlaceholder}\n noResultsLabel={noResultsText}\n disabled={disabled || isLoading}\n className={className}\n dropdownWidth={dropdownWidth}\n renderTrigger={({ selectedItem }) => {\n if (isLoading) {\n return (\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <SpinnerGap className=\"h-4 w-4 animate-spin\" />\n {loadingText}\n </span>\n );\n }\n\n if (selectedItem) {\n return <span style={{ fontFamily: selectedItem.value }}>{selectedItem.label}</span>;\n }\n\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }}\n renderItem={({ item, isSelected, onSelect }) => (\n <FontPickerItem font={item} isSelected={isSelected} onSelect={onSelect} />\n )}\n />\n );\n}\n\nexport default FontPicker;\n"],"names":["FontPickerItem"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Crown, Copy, SidebarSimple, Lightning, Question, Sparkle } from '@phosphor-icons/react';
|
|
3
3
|
import { L as Logo } from './logo.BXk28Fqo.js';
|
|
4
|
-
import { Button } from '
|
|
4
|
+
import { B as Button } from './button.DQL6gCAt.js';
|
|
5
5
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuPortal, DropdownMenuSubContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuShortcut, DropdownMenuItem } from '../components/ui/dropdown-menu.js';
|
|
6
6
|
import { Avatar, AvatarImage, AvatarFallback, AvatarBadge } from '../components/ui/avatar.js';
|
|
7
7
|
import { c as cn } from './utils.Cwtlq8dh.js';
|
|
@@ -192,4 +192,4 @@ const HeaderNav = React.forwardRef(function HeaderNav2({
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
export { HEADER_NAV_HEIGHT as H, HeaderNav as a };
|
|
195
|
-
//# sourceMappingURL=header-nav.
|
|
195
|
+
//# sourceMappingURL=header-nav.C1uX9mgG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header-nav.BxK3FN1j.js","sources":["../../../src/layouts/header-nav/account-dropdown.tsx","../../../src/layouts/header-nav/header-nav.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Copy, Crown } from '@phosphor-icons/react';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '../../components/ui/dropdown-menu';\nimport { Avatar, AvatarFallback, AvatarImage, AvatarBadge } from '../../components/ui/avatar';\nimport { Button } from '../../components/ui/button';\n\nimport { cn } from '@/lib/utils';\n\nexport type AccountDropdownActionItem = {\n type?: 'action';\n id: string;\n label: string;\n icon?: React.ReactNode;\n onClick: () => void;\n /** Second line (e.g. \"ID: xyz\"); copy button shown when copyValue is set. */\n secondaryLabel?: React.ReactNode;\n copyValue?: string;\n onCopy?: (value: string) => void;\n /** Keyboard shortcut hint (e.g. \"⌘K\") shown on the right. */\n shortcut?: string;\n};\n\nexport type AccountDropdownSubOption = {\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Required for radio mode. */\n value?: string;\n /** Used in plain (non-radio) mode. */\n onClick?: () => void;\n /** Keyboard shortcut hint (e.g. \"⌘K\") shown on the right. */\n shortcut?: string;\n};\n\n/** Sub-option with a required `value`, used in radio-mode submenus. */\nexport type AccountDropdownRadioSubOption = Omit<AccountDropdownSubOption, 'value' | 'onClick'> & {\n value: string;\n};\n\ntype AccountDropdownSubmenuBase = {\n type: 'submenu';\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Second line on the submenu trigger (e.g. \"ID: xyz\"); copy button when copyValue is set. */\n secondaryLabel?: React.ReactNode;\n copyValue?: string;\n onCopy?: (value: string) => void;\n};\n\nexport type AccountDropdownSubmenuItem = AccountDropdownSubmenuBase &\n (\n | {\n /** The currently selected value. When provided with onValueChange, renders items as a radio group with selection indicators. */\n value: string;\n onValueChange: (value: string) => void;\n items: AccountDropdownRadioSubOption[];\n }\n | {\n value?: never;\n onValueChange?: never;\n items: AccountDropdownSubOption[];\n }\n );\n\nexport type AccountDropdownItem = AccountDropdownActionItem | AccountDropdownSubmenuItem;\n\nexport type AccountDropdownTeam = {\n id: string;\n name: string;\n isCurrent: boolean;\n logoUrl?: string;\n};\n\nexport interface AccountDropdownProps extends React.ComponentPropsWithoutRef<typeof DropdownMenu> {\n accountPhoto: string;\n accountName: string;\n /** Pass a flat array for a single group, or an array of arrays for multiple groups separated by dividers. */\n accountDropdownItems: AccountDropdownItem[] | AccountDropdownItem[][];\n teams: AccountDropdownTeam[];\n /** Side the dropdown opens on relative to the trigger. Defaults to 'bottom'. */\n side?: React.ComponentPropsWithoutRef<typeof DropdownMenuContent>['side'];\n /** Alignment of the dropdown relative to the trigger. Defaults to 'end'. */\n align?: React.ComponentPropsWithoutRef<typeof DropdownMenuContent>['align'];\n isSuperAdmin?: boolean;\n}\n\nexport function AccountDropdown({\n accountPhoto,\n accountName,\n accountDropdownItems,\n teams,\n side = 'bottom',\n align = 'end',\n isSuperAdmin = false,\n ...props\n}: AccountDropdownProps) {\n const showTeamName = teams?.length > 1 || isSuperAdmin;\n const currentTeamName = (showTeamName && teams?.find((el) => el.isCurrent)?.name) || '';\n const initial = accountName[0];\n\n const groups: AccountDropdownItem[][] = Array.isArray(accountDropdownItems[0])\n ? (accountDropdownItems as AccountDropdownItem[][])\n : [accountDropdownItems as AccountDropdownItem[]];\n\n const handleCopy = React.useCallback((value: string, onCopy?: (value: string) => void) => {\n return (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onCopy) onCopy(value);\n else navigator.clipboard.writeText(value);\n };\n }, []);\n\n const renderCopyRow = (\n secondaryLabel: React.ReactNode,\n copyValue: string | undefined,\n onCopy?: (value: string) => void,\n ) =>\n secondaryLabel && (\n <div className=\"flex w-full items-center gap-1 text-xs text-subtlest ml-7\">\n {secondaryLabel}\n {copyValue != null && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-4 shrink-0 p-0 [&>svg]:!size-3\"\n onClick={handleCopy(copyValue, onCopy)}\n aria-label=\"Copy ID\"\n >\n <Copy className=\"size-3\" />\n </Button>\n )}\n </div>\n );\n\n return (\n <DropdownMenu {...props}>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"default\"\n variant=\"ghost\"\n className=\"rounded-full p-[1px] border border-dark-300 relative\"\n aria-label=\"Toggle account dropdown\"\n >\n <Avatar>\n <AvatarImage\n src={accountPhoto}\n alt={`${accountName}'s account`}\n className={cn(\n 'block rounded-full border border-background',\n isSuperAdmin && 'border-2 border-solid border-red-700 inset-1',\n )}\n />\n <AvatarFallback>{initial}</AvatarFallback>\n {isSuperAdmin && (\n <AvatarBadge className=\"bg-red-700 text-white\">\n <Crown />\n </AvatarBadge>\n )}\n </Avatar>\n {showTeamName && <span className=\"text-xs text-default font-semibold pr-1\">{currentTeamName}</span>}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n side={side}\n align={align}\n className=\"border-none shadow-[2px_4px_12px_0px_rgba(0,0,0,0.14)] dark:shadow-[2px_4px_12px_0px_rgba(255,255,255,0.14)]\"\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={groupIndex}>\n {groupIndex > 0 && <DropdownMenuSeparator />}\n <DropdownMenuGroup>\n {group.map((item) =>\n item.type === 'submenu' ? (\n <DropdownMenuSub key={item.id}>\n <DropdownMenuSubTrigger\n secondaryRow={renderCopyRow(item.secondaryLabel, item.copyValue, item.onCopy)}\n >\n {item.icon}\n {item.label}\n </DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent className=\"border-none shadow-[2px_4px_12px_0px_rgba(0,0,0,0.14)] dark:shadow-[2px_4px_12px_0px_rgba(255,255,255,0.14)]\">\n {item.value != null && item.onValueChange ? (\n <DropdownMenuRadioGroup value={item.value} onValueChange={item.onValueChange}>\n {item.items.map((option) => (\n <DropdownMenuRadioItem key={option.id} value={option.value}>\n {option.icon}\n {option.label}\n {option.shortcut != null && (\n <DropdownMenuShortcut>{option.shortcut}</DropdownMenuShortcut>\n )}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n ) : (\n item.items.map((option) => (\n <DropdownMenuItem key={option.id} onClick={option.onClick}>\n {option.icon}\n {option.label}\n {option.shortcut != null && (\n <DropdownMenuShortcut>{option.shortcut}</DropdownMenuShortcut>\n )}\n </DropdownMenuItem>\n ))\n )}\n </DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSub>\n ) : (\n <DropdownMenuItem\n key={item.id}\n onClick={item.onClick}\n secondaryRow={renderCopyRow(item.secondaryLabel, item.copyValue, item.onCopy)}\n >\n {item.icon}\n {item.label}\n {item.shortcut != null && <DropdownMenuShortcut>{item.shortcut}</DropdownMenuShortcut>}\n </DropdownMenuItem>\n ),\n )}\n </DropdownMenuGroup>\n </React.Fragment>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import * as React from 'react';\nimport { Question, SidebarSimple, Lightning, Sparkle } from '@phosphor-icons/react';\n\nimport { Logo } from '../../components/logo';\nimport { Button } from '../../components/ui/button';\nimport { AccountDropdown, AccountDropdownProps } from './account-dropdown';\n\nimport { cn } from '@/lib/utils';\nimport { useBooleanFlagValue } from '@/lib/feature-flags';\n\ninterface HeaderNavProps extends React.ComponentPropsWithoutRef<'header'>, Omit<AccountDropdownProps, 'dir'> {\n isSideNavOpen?: boolean;\n onSideNavigationToggle: () => void;\n onHelpClick: () => void;\n onBrainfishNativeClick: () => void;\n onLogoNav: () => void;\n isHomePath?: boolean;\n showSuggestionAction?: boolean;\n suggestionAction?: React.ReactNode;\n onSuggestionActionClick?: () => void;\n showSidebarToggle?: boolean;\n isSuperAdmin?: boolean;\n /** Ref for the sidebar toggle button; used by layout to move focus here when sidebar is collapsed. */\n sidebarToggleRef?: React.Ref<HTMLButtonElement>;\n}\n\nexport const HEADER_NAV_HEIGHT = 60;\n\nexport const HeaderNav = React.forwardRef<HTMLElement, HeaderNavProps>(function HeaderNav(\n {\n className,\n isSideNavOpen = false,\n onSideNavigationToggle,\n onHelpClick,\n onBrainfishNativeClick,\n accountName,\n accountPhoto,\n accountDropdownItems,\n teams,\n side,\n align,\n showSuggestionAction,\n suggestionAction,\n onSuggestionActionClick,\n onLogoNav,\n isHomePath = false,\n showSidebarToggle = true,\n sidebarToggleRef,\n isSuperAdmin,\n ...props\n },\n ref,\n) {\n const hasSuggestionAction = showSuggestionAction && !!suggestionAction && !!onSuggestionActionClick;\n const brainfishNativeEnabled = useBooleanFlagValue('platform.brainfish-native.enabled', false);\n\n return (\n <header ref={ref} {...props} className={cn('px-4 py-3 relative', className)}>\n <nav aria-label=\"Account navigation\" className=\"flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n <a\n href=\"/\"\n onClick={(e) => {\n const isPlainLeftClick = e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;\n\n if (isPlainLeftClick) {\n e.preventDefault();\n onLogoNav();\n }\n }}\n aria-current={isHomePath ? 'page' : undefined}\n >\n <Logo\n variant=\"full\"\n color={isHomePath ? 'fill' : 'outline'}\n width={130}\n height={20}\n className=\"hidden md:block\"\n />\n <Logo\n variant=\"mark\"\n color={isHomePath ? 'fill' : 'outline'}\n width={37}\n height={20}\n className=\"block md:hidden\"\n />\n </a>\n {showSidebarToggle && (\n <Button\n ref={sidebarToggleRef}\n size=\"icon\"\n variant=\"ghost\"\n aria-label=\"Toggle side navigation\"\n className=\"[&_svg]:size-6\"\n onClick={onSideNavigationToggle}\n >\n <SidebarSimple aria-hidden=\"true\" weight={isSideNavOpen ? 'fill' : 'regular'} />\n </Button>\n )}\n </div>\n <div className=\"flex items-center gap-4\">\n {hasSuggestionAction && (\n <Button variant=\"suggestion\" onClick={onSuggestionActionClick}>\n <Lightning weight=\"fill\" aria-hidden=\"true\" /> {suggestionAction}\n </Button>\n )}\n <Button size=\"icon\" variant=\"ghost\" aria-label=\"Open help\" className=\"[&_svg]:size-6\" onClick={onHelpClick}>\n <Question aria-hidden=\"true\" />\n </Button>\n {brainfishNativeEnabled && (\n <Button\n size=\"icon\"\n aria-label=\"Open Brainfish Native\"\n className=\"[&_svg]:size-4 size-6 rounded-3xl bg-yellowfin-gradient hover:bg-yellowfin-gradient-reverse focus-visible:bg-yellowfin-gradient-reverse\"\n style={\n {\n cornerShape: 'squircle',\n } as React.CSSProperties\n }\n onClick={onBrainfishNativeClick}\n >\n <span className=\"relative\">\n <Sparkle aria-hidden=\"true\" weight=\"fill\" color=\"white\" className=\"relative z-10\" />\n <Sparkle\n aria-hidden=\"true\"\n weight=\"fill\"\n className=\"text-dark-800 opacity-20 absolute z-0 left-[1px] top-[1px]\"\n />\n </span>\n </Button>\n )}\n <AccountDropdown\n accountName={accountName}\n accountPhoto={accountPhoto}\n accountDropdownItems={accountDropdownItems}\n teams={teams}\n side={side}\n align={align}\n isSuperAdmin={isSuperAdmin}\n />\n </div>\n </nav>\n </header>\n );\n});\n"],"names":["HeaderNav"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"header-nav.C1uX9mgG.js","sources":["../../../src/layouts/header-nav/account-dropdown.tsx","../../../src/layouts/header-nav/header-nav.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Copy, Crown } from '@phosphor-icons/react';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '../../components/ui/dropdown-menu';\nimport { Avatar, AvatarFallback, AvatarImage, AvatarBadge } from '../../components/ui/avatar';\nimport { Button } from '../../components/ui/button';\n\nimport { cn } from '@/lib/utils';\n\nexport type AccountDropdownActionItem = {\n type?: 'action';\n id: string;\n label: string;\n icon?: React.ReactNode;\n onClick: () => void;\n /** Second line (e.g. \"ID: xyz\"); copy button shown when copyValue is set. */\n secondaryLabel?: React.ReactNode;\n copyValue?: string;\n onCopy?: (value: string) => void;\n /** Keyboard shortcut hint (e.g. \"⌘K\") shown on the right. */\n shortcut?: string;\n};\n\nexport type AccountDropdownSubOption = {\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Required for radio mode. */\n value?: string;\n /** Used in plain (non-radio) mode. */\n onClick?: () => void;\n /** Keyboard shortcut hint (e.g. \"⌘K\") shown on the right. */\n shortcut?: string;\n};\n\n/** Sub-option with a required `value`, used in radio-mode submenus. */\nexport type AccountDropdownRadioSubOption = Omit<AccountDropdownSubOption, 'value' | 'onClick'> & {\n value: string;\n};\n\ntype AccountDropdownSubmenuBase = {\n type: 'submenu';\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Second line on the submenu trigger (e.g. \"ID: xyz\"); copy button when copyValue is set. */\n secondaryLabel?: React.ReactNode;\n copyValue?: string;\n onCopy?: (value: string) => void;\n};\n\nexport type AccountDropdownSubmenuItem = AccountDropdownSubmenuBase &\n (\n | {\n /** The currently selected value. When provided with onValueChange, renders items as a radio group with selection indicators. */\n value: string;\n onValueChange: (value: string) => void;\n items: AccountDropdownRadioSubOption[];\n }\n | {\n value?: never;\n onValueChange?: never;\n items: AccountDropdownSubOption[];\n }\n );\n\nexport type AccountDropdownItem = AccountDropdownActionItem | AccountDropdownSubmenuItem;\n\nexport type AccountDropdownTeam = {\n id: string;\n name: string;\n isCurrent: boolean;\n logoUrl?: string;\n};\n\nexport interface AccountDropdownProps extends React.ComponentPropsWithoutRef<typeof DropdownMenu> {\n accountPhoto: string;\n accountName: string;\n /** Pass a flat array for a single group, or an array of arrays for multiple groups separated by dividers. */\n accountDropdownItems: AccountDropdownItem[] | AccountDropdownItem[][];\n teams: AccountDropdownTeam[];\n /** Side the dropdown opens on relative to the trigger. Defaults to 'bottom'. */\n side?: React.ComponentPropsWithoutRef<typeof DropdownMenuContent>['side'];\n /** Alignment of the dropdown relative to the trigger. Defaults to 'end'. */\n align?: React.ComponentPropsWithoutRef<typeof DropdownMenuContent>['align'];\n isSuperAdmin?: boolean;\n}\n\nexport function AccountDropdown({\n accountPhoto,\n accountName,\n accountDropdownItems,\n teams,\n side = 'bottom',\n align = 'end',\n isSuperAdmin = false,\n ...props\n}: AccountDropdownProps) {\n const showTeamName = teams?.length > 1 || isSuperAdmin;\n const currentTeamName = (showTeamName && teams?.find((el) => el.isCurrent)?.name) || '';\n const initial = accountName[0];\n\n const groups: AccountDropdownItem[][] = Array.isArray(accountDropdownItems[0])\n ? (accountDropdownItems as AccountDropdownItem[][])\n : [accountDropdownItems as AccountDropdownItem[]];\n\n const handleCopy = React.useCallback((value: string, onCopy?: (value: string) => void) => {\n return (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onCopy) onCopy(value);\n else navigator.clipboard.writeText(value);\n };\n }, []);\n\n const renderCopyRow = (\n secondaryLabel: React.ReactNode,\n copyValue: string | undefined,\n onCopy?: (value: string) => void,\n ) =>\n secondaryLabel && (\n <div className=\"flex w-full items-center gap-1 text-xs text-subtlest ml-7\">\n {secondaryLabel}\n {copyValue != null && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-4 shrink-0 p-0 [&>svg]:!size-3\"\n onClick={handleCopy(copyValue, onCopy)}\n aria-label=\"Copy ID\"\n >\n <Copy className=\"size-3\" />\n </Button>\n )}\n </div>\n );\n\n return (\n <DropdownMenu {...props}>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"default\"\n variant=\"ghost\"\n className=\"rounded-full p-[1px] border border-dark-300 relative\"\n aria-label=\"Toggle account dropdown\"\n >\n <Avatar>\n <AvatarImage\n src={accountPhoto}\n alt={`${accountName}'s account`}\n className={cn(\n 'block rounded-full border border-background',\n isSuperAdmin && 'border-2 border-solid border-red-700 inset-1',\n )}\n />\n <AvatarFallback>{initial}</AvatarFallback>\n {isSuperAdmin && (\n <AvatarBadge className=\"bg-red-700 text-white\">\n <Crown />\n </AvatarBadge>\n )}\n </Avatar>\n {showTeamName && <span className=\"text-xs text-default font-semibold pr-1\">{currentTeamName}</span>}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n side={side}\n align={align}\n className=\"border-none shadow-[2px_4px_12px_0px_rgba(0,0,0,0.14)] dark:shadow-[2px_4px_12px_0px_rgba(255,255,255,0.14)]\"\n >\n {groups.map((group, groupIndex) => (\n <React.Fragment key={groupIndex}>\n {groupIndex > 0 && <DropdownMenuSeparator />}\n <DropdownMenuGroup>\n {group.map((item) =>\n item.type === 'submenu' ? (\n <DropdownMenuSub key={item.id}>\n <DropdownMenuSubTrigger\n secondaryRow={renderCopyRow(item.secondaryLabel, item.copyValue, item.onCopy)}\n >\n {item.icon}\n {item.label}\n </DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent className=\"border-none shadow-[2px_4px_12px_0px_rgba(0,0,0,0.14)] dark:shadow-[2px_4px_12px_0px_rgba(255,255,255,0.14)]\">\n {item.value != null && item.onValueChange ? (\n <DropdownMenuRadioGroup value={item.value} onValueChange={item.onValueChange}>\n {item.items.map((option) => (\n <DropdownMenuRadioItem key={option.id} value={option.value}>\n {option.icon}\n {option.label}\n {option.shortcut != null && (\n <DropdownMenuShortcut>{option.shortcut}</DropdownMenuShortcut>\n )}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n ) : (\n item.items.map((option) => (\n <DropdownMenuItem key={option.id} onClick={option.onClick}>\n {option.icon}\n {option.label}\n {option.shortcut != null && (\n <DropdownMenuShortcut>{option.shortcut}</DropdownMenuShortcut>\n )}\n </DropdownMenuItem>\n ))\n )}\n </DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSub>\n ) : (\n <DropdownMenuItem\n key={item.id}\n onClick={item.onClick}\n secondaryRow={renderCopyRow(item.secondaryLabel, item.copyValue, item.onCopy)}\n >\n {item.icon}\n {item.label}\n {item.shortcut != null && <DropdownMenuShortcut>{item.shortcut}</DropdownMenuShortcut>}\n </DropdownMenuItem>\n ),\n )}\n </DropdownMenuGroup>\n </React.Fragment>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import * as React from 'react';\nimport { Question, SidebarSimple, Lightning, Sparkle } from '@phosphor-icons/react';\n\nimport { Logo } from '../../components/logo';\nimport { Button } from '../../components/ui/button';\nimport { AccountDropdown, AccountDropdownProps } from './account-dropdown';\n\nimport { cn } from '@/lib/utils';\nimport { useBooleanFlagValue } from '@/lib/feature-flags';\n\ninterface HeaderNavProps extends React.ComponentPropsWithoutRef<'header'>, Omit<AccountDropdownProps, 'dir'> {\n isSideNavOpen?: boolean;\n onSideNavigationToggle: () => void;\n onHelpClick: () => void;\n onBrainfishNativeClick: () => void;\n onLogoNav: () => void;\n isHomePath?: boolean;\n showSuggestionAction?: boolean;\n suggestionAction?: React.ReactNode;\n onSuggestionActionClick?: () => void;\n showSidebarToggle?: boolean;\n isSuperAdmin?: boolean;\n /** Ref for the sidebar toggle button; used by layout to move focus here when sidebar is collapsed. */\n sidebarToggleRef?: React.Ref<HTMLButtonElement>;\n}\n\nexport const HEADER_NAV_HEIGHT = 60;\n\nexport const HeaderNav = React.forwardRef<HTMLElement, HeaderNavProps>(function HeaderNav(\n {\n className,\n isSideNavOpen = false,\n onSideNavigationToggle,\n onHelpClick,\n onBrainfishNativeClick,\n accountName,\n accountPhoto,\n accountDropdownItems,\n teams,\n side,\n align,\n showSuggestionAction,\n suggestionAction,\n onSuggestionActionClick,\n onLogoNav,\n isHomePath = false,\n showSidebarToggle = true,\n sidebarToggleRef,\n isSuperAdmin,\n ...props\n },\n ref,\n) {\n const hasSuggestionAction = showSuggestionAction && !!suggestionAction && !!onSuggestionActionClick;\n const brainfishNativeEnabled = useBooleanFlagValue('platform.brainfish-native.enabled', false);\n\n return (\n <header ref={ref} {...props} className={cn('px-4 py-3 relative', className)}>\n <nav aria-label=\"Account navigation\" className=\"flex justify-between items-center\">\n <div className=\"flex items-center gap-2\">\n <a\n href=\"/\"\n onClick={(e) => {\n const isPlainLeftClick = e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;\n\n if (isPlainLeftClick) {\n e.preventDefault();\n onLogoNav();\n }\n }}\n aria-current={isHomePath ? 'page' : undefined}\n >\n <Logo\n variant=\"full\"\n color={isHomePath ? 'fill' : 'outline'}\n width={130}\n height={20}\n className=\"hidden md:block\"\n />\n <Logo\n variant=\"mark\"\n color={isHomePath ? 'fill' : 'outline'}\n width={37}\n height={20}\n className=\"block md:hidden\"\n />\n </a>\n {showSidebarToggle && (\n <Button\n ref={sidebarToggleRef}\n size=\"icon\"\n variant=\"ghost\"\n aria-label=\"Toggle side navigation\"\n className=\"[&_svg]:size-6\"\n onClick={onSideNavigationToggle}\n >\n <SidebarSimple aria-hidden=\"true\" weight={isSideNavOpen ? 'fill' : 'regular'} />\n </Button>\n )}\n </div>\n <div className=\"flex items-center gap-4\">\n {hasSuggestionAction && (\n <Button variant=\"suggestion\" onClick={onSuggestionActionClick}>\n <Lightning weight=\"fill\" aria-hidden=\"true\" /> {suggestionAction}\n </Button>\n )}\n <Button size=\"icon\" variant=\"ghost\" aria-label=\"Open help\" className=\"[&_svg]:size-6\" onClick={onHelpClick}>\n <Question aria-hidden=\"true\" />\n </Button>\n {brainfishNativeEnabled && (\n <Button\n size=\"icon\"\n aria-label=\"Open Brainfish Native\"\n className=\"[&_svg]:size-4 size-6 rounded-3xl bg-yellowfin-gradient hover:bg-yellowfin-gradient-reverse focus-visible:bg-yellowfin-gradient-reverse\"\n style={\n {\n cornerShape: 'squircle',\n } as React.CSSProperties\n }\n onClick={onBrainfishNativeClick}\n >\n <span className=\"relative\">\n <Sparkle aria-hidden=\"true\" weight=\"fill\" color=\"white\" className=\"relative z-10\" />\n <Sparkle\n aria-hidden=\"true\"\n weight=\"fill\"\n className=\"text-dark-800 opacity-20 absolute z-0 left-[1px] top-[1px]\"\n />\n </span>\n </Button>\n )}\n <AccountDropdown\n accountName={accountName}\n accountPhoto={accountPhoto}\n accountDropdownItems={accountDropdownItems}\n teams={teams}\n side={side}\n align={align}\n isSuperAdmin={isSuperAdmin}\n />\n </div>\n </nav>\n </header>\n );\n});\n"],"names":["HeaderNav"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React__default, { useContext, useState, useMemo, useRef, useEffect, useCallback, isValidElement } from 'react';
|
|
2
2
|
import { useMediaQuery } from 'usehooks-ts';
|
|
3
|
-
import { a as HeaderNav, H as HEADER_NAV_HEIGHT } from './header-nav.
|
|
3
|
+
import { a as HeaderNav, H as HEADER_NAV_HEIGHT } from './header-nav.C1uX9mgG.js';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
5
|
import { c as cn } from './utils.Cwtlq8dh.js';
|
|
6
6
|
import { ScrollArea } from '../components/ui/scroll-area.js';
|
|
7
7
|
import { F as FeatureFlagProvider } from './feature-flags.C57XMODn.js';
|
|
8
8
|
import { Item } from '../components/ui/item.js';
|
|
9
|
-
import { S as Sidebar } from './sidebar.
|
|
9
|
+
import { S as Sidebar } from './sidebar.CYhTQT2L.js';
|
|
10
10
|
|
|
11
11
|
const FullLayoutNavStateContext = React__default.createContext(null);
|
|
12
12
|
const FullLayoutContext = React__default.createContext(null);
|
|
@@ -503,4 +503,4 @@ const FullLayout = Object.assign(FullLayoutWithFlags, {
|
|
|
503
503
|
});
|
|
504
504
|
|
|
505
505
|
export { FullLayout as F, FullLayoutLeftSidebar as a, FullLayoutNavStateContext as b, FullLayoutProvider as c, FullLayoutRightSidebar as d, useRightSidebar as e, useFullLayoutContext as u };
|
|
506
|
-
//# sourceMappingURL=layout.
|
|
506
|
+
//# sourceMappingURL=layout.CLxqWeQt.js.map
|