frappe-ui 0.1.216 → 0.1.218

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/frappe/Billing/SignupBanner.vue +1 -1
  2. package/frappe/Billing/TrialBanner.vue +1 -1
  3. package/frappe/Help/HelpModal.vue +4 -4
  4. package/frappe/Onboarding/GettingStartedBanner.vue +1 -1
  5. package/frappe/index.d.ts +53 -0
  6. package/package.json +25 -2
  7. package/src/components/Charts/index.ts +0 -0
  8. package/src/components/Combobox/Combobox.story.vue +18 -0
  9. package/src/components/Combobox/Combobox.vue +13 -2
  10. package/src/components/Combobox/types.ts +2 -1
  11. package/src/components/DatePicker/index.ts +6 -0
  12. package/src/components/Dropdown/Dropdown.vue +19 -5
  13. package/src/components/Dropdown/types.ts +1 -0
  14. package/src/components/ListView/ListGroupHeader.vue +1 -1
  15. package/src/components/ListView/ListGroupRows.vue +5 -0
  16. package/src/components/Select/Select.story.vue +16 -3
  17. package/src/components/Select/Select.vue +109 -96
  18. package/src/components/Sidebar/index.ts +3 -0
  19. package/src/components/Toast/Toast.vue +1 -1
  20. package/src/data-fetching/index.ts +4 -2
  21. package/src/index.ts +9 -23
  22. package/src/resources/{index.js → index.ts} +3 -1
  23. package/src/resources/{local.js → local.ts} +4 -4
  24. package/src/resources/realtime.ts +21 -0
  25. package/frappe/Icons/HelpIcon.vue +0 -16
  26. package/frappe/Icons/LightningIcon.vue +0 -16
  27. package/frappe/Icons/MaximizeIcon.vue +0 -19
  28. package/frappe/Icons/MinimizeIcon.vue +0 -19
  29. package/frappe/Icons/StepsIcon.vue +0 -16
  30. package/src/components/GreenCheckIcon.vue +0 -16
  31. package/src/icons/CircleCheck.vue +0 -9
  32. package/src/icons/DownSolid.vue +0 -8
  33. package/src/resources/realtime.js +0 -15
@@ -25,7 +25,7 @@
25
25
  </Button>
26
26
  </template>
27
27
  <script setup>
28
- import LightningIcon from '../Icons/LightningIcon.vue'
28
+ import LightningIcon from '../../icons/LightningIcon.vue'
29
29
 
30
30
  const props = defineProps({
31
31
  isSidebarCollapsed: {
@@ -23,7 +23,7 @@
23
23
  </Button>
24
24
  </template>
25
25
  <script setup>
26
- import LightningIcon from '../Icons/LightningIcon.vue'
26
+ import LightningIcon from '../../icons/LightningIcon.vue'
27
27
  import FeatherIcon from '../../src/components/FeatherIcon.vue'
28
28
  import { Button } from '../../src/components/Button'
29
29
  import { createResource } from '../../src/resources'
@@ -55,10 +55,10 @@
55
55
  <script setup>
56
56
  import Dropdown from '../../src/components/Dropdown/Dropdown.vue'
57
57
  import Button from '../../src/components/Button/Button.vue'
58
- import StepsIcon from '../Icons/StepsIcon.vue'
59
- import MinimizeIcon from '../Icons/MinimizeIcon.vue'
60
- import MaximizeIcon from '../Icons/MaximizeIcon.vue'
61
- import HelpIcon from '../Icons/HelpIcon.vue'
58
+ import StepsIcon from '../../icons/StepsIcon.vue'
59
+ import MinimizeIcon from '../../icons/MinimizeIcon.vue'
60
+ import MaximizeIcon from '../../icons/MaximizeIcon.vue'
61
+ import HelpIcon from '../../icons/HelpIcon.vue'
62
62
  import OnboardingSteps from '../Onboarding/OnboardingSteps.vue'
63
63
  import HelpCenter from '../HelpCenter/HelpCenter.vue'
64
64
  import { useOnboarding } from '../Onboarding/onboarding'
@@ -56,7 +56,7 @@
56
56
  </Button>
57
57
  </template>
58
58
  <script setup>
59
- import StepsIcon from '../Icons/StepsIcon.vue'
59
+ import StepsIcon from '../../icons/StepsIcon.vue'
60
60
  import Button from '../../src/components/Button/Button.vue'
61
61
  import FeatherIcon from '../../src/components/FeatherIcon.vue'
62
62
  import { useOnboarding } from './onboarding'
@@ -0,0 +1,53 @@
1
+ // Since the export is via JS file, we need to declare the module here
2
+ declare module 'frappe-ui/frappe' {
3
+ import type { Component, ComputedRef, Ref } from 'vue'
4
+
5
+ // Onboarding
6
+ export interface OnboardingStep {
7
+ name: string
8
+ completed: boolean
9
+ [key: string]: any
10
+ }
11
+
12
+ export function useOnboarding(appName: string):
13
+ | {
14
+ steps: OnboardingStep[]
15
+ stepsCompleted: ComputedRef<number>
16
+ totalSteps: ComputedRef<number>
17
+ completedPercentage: ComputedRef<number>
18
+ isOnboardingStepsCompleted: Ref<boolean>
19
+ updateOnboardingStep: (
20
+ step: string,
21
+ value?: boolean,
22
+ skipped?: boolean,
23
+ callback?: ((step: string, skipped: boolean) => void) | null,
24
+ ) => void
25
+ skip: (
26
+ step: string,
27
+ callback?: ((step: string, skipped: boolean) => void) | null,
28
+ ) => void
29
+ skipAll: (callback?: ((value: boolean) => void) | null) => void
30
+ reset: (
31
+ step: string,
32
+ callback?: ((step: string, skipped: boolean) => void) | null,
33
+ ) => void
34
+ resetAll: (callback?: ((value: boolean) => void) | null) => void
35
+ setUp: (steps: OnboardingStep[]) => void
36
+ syncStatus: () => void
37
+ }
38
+ | undefined
39
+
40
+ // Help Modal
41
+ export const showHelpModal: Ref<boolean>
42
+ export const minimize: Ref<boolean>
43
+ export const HelpModal: Component
44
+
45
+ // Banners
46
+ export const GettingStartedBanner: Component
47
+ export const TrialBanner: Component
48
+ export const IntermediateStepModal: Component
49
+
50
+ // Components
51
+ export const Link: Component
52
+ export type { LinkProps } from './Link/types'
53
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "frappe-ui",
3
- "version": "0.1.216",
3
+ "version": "0.1.218",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
- "main": "./src/index.ts",
6
5
  "type": "module",
6
+ "sideEffects": false,
7
7
  "scripts": {
8
8
  "test": "vitest --run",
9
9
  "type-check": "tsc --noEmit",
@@ -17,6 +17,29 @@
17
17
  "story:build": "histoire build && cp 404.html .histoire/dist",
18
18
  "story:preview": "histoire preview"
19
19
  },
20
+ "exports": {
21
+ ".": {
22
+ "import": "./src/index.ts",
23
+ "types": "./src/index.ts"
24
+ },
25
+ "./frappe": {
26
+ "import": "./frappe/index.js"
27
+ },
28
+ "./icons": {
29
+ "import": "./icons/index.ts"
30
+ },
31
+ "./tailwind": {
32
+ "import": "./src/tailwind/preset.js",
33
+ "default": "./src/tailwind/preset.js"
34
+ },
35
+ "./vite": {
36
+ "import": "./vite/index.js"
37
+ },
38
+ "./style.css": {
39
+ "import": "./src/style.css"
40
+ },
41
+ "./tsconfig.base.json": "./tsconfig.base.json"
42
+ },
20
43
  "files": [
21
44
  "frappe",
22
45
  "src",
File without changes
@@ -178,6 +178,24 @@ const state = reactive({
178
178
  </div>
179
179
  </Variant>
180
180
 
181
+ <Variant title="Outline variant">
182
+ <div class="p-4">
183
+ <label class="block text-sm font-medium mb-2">Simple Options</label>
184
+ <Combobox
185
+ variant="outline"
186
+ :options="simpleOptions"
187
+ v-model="simpleValue"
188
+ :placeholder="state.placeholder"
189
+ :disabled="state.disabled"
190
+ :show-cancel="state.showCancel"
191
+ @update:selectedOption="selectedOption = $event"
192
+ />
193
+ <div class="mt-2 text-sm text-gray-600">
194
+ Selected: {{ simpleValue || 'None' }}
195
+ </div>
196
+ </div>
197
+ </Variant>
198
+
181
199
  <Variant title="Object Options">
182
200
  <div class="p-4">
183
201
  <label class="block text-sm font-medium mb-2">Object Options</label>
@@ -33,6 +33,7 @@ import type {
33
33
  } from './types'
34
34
 
35
35
  const props = withDefaults(defineProps<ComboboxProps>(), {
36
+ variant: 'subtle',
36
37
  options: () => [],
37
38
  })
38
39
  const emit = defineEmits([
@@ -279,6 +280,13 @@ const reset = () => {
279
280
  emit('update:selectedOption', null)
280
281
  }
281
282
 
283
+ const variantClasses = computed(() => {
284
+ return {
285
+ subtle: 'bg-surface-gray-2 hover:bg-surface-gray-3 border-transparent',
286
+ outline: 'border-outline-gray-2',
287
+ }[props.variant]
288
+ })
289
+
282
290
  defineExpose({
283
291
  reset,
284
292
  })
@@ -294,8 +302,11 @@ defineExpose({
294
302
  :open="isOpen"
295
303
  >
296
304
  <ComboboxAnchor
297
- class="flex h-7 w-full items-center justify-between gap-2 rounded bg-surface-gray-2 px-2 py-1 transition-colors hover:bg-surface-gray-3 border border-transparent focus-within:border-outline-gray-4 focus-within:ring-2 focus-within:ring-outline-gray-3"
298
- :class="{ 'opacity-50 pointer-events-none': disabled }"
305
+ class="flex h-7 w-full items-center justify-between gap-2 rounded px-2 py-1 transition-colors border focus-within:border-outline-gray-4 focus-within:ring-2 focus-within:ring-outline-gray-3"
306
+ :class="{
307
+ 'opacity-50 pointer-events-none': disabled,
308
+ [variantClasses]: true,
309
+ }"
299
310
  @click="handleClick"
300
311
  >
301
312
  <div class="flex items-center gap-2 flex-1 overflow-hidden">
@@ -26,6 +26,7 @@ export type GroupedOption = { group: string; options: SimpleOption[] }
26
26
  export type ComboboxOption = SimpleOption | GroupedOption
27
27
 
28
28
  export interface ComboboxProps {
29
+ variant?: 'subtle' | 'outline'
29
30
  options: Array<ComboboxOption>
30
31
  modelValue?: string | null
31
32
  placeholder?: string
@@ -33,4 +34,4 @@ export interface ComboboxProps {
33
34
  openOnFocus?: boolean
34
35
  openOnClick?: boolean
35
36
  placement?: 'start' | 'center' | 'end'
36
- }
37
+ }
@@ -0,0 +1,6 @@
1
+ export { default as DatePicker } from './DatePicker.vue'
2
+ export { default as DateRangePicker } from './DateRangePicker.vue'
3
+ export { default as DateTimePicker } from './DateTimePicker.vue'
4
+ export * from './types'
5
+ export { useDatePicker } from './useDatePicker'
6
+ export * from './utils'
@@ -53,7 +53,13 @@
53
53
  :model-value="item.switchValue || false"
54
54
  />
55
55
  </div>
56
- <DropdownMenuItem v-else as-child @select="item.onClick">
56
+ <DropdownMenuItem
57
+ v-else
58
+ as-child
59
+ @select="item.onClick"
60
+ :disabled="item.disabled"
61
+ class="data-[disabled]:cursor-not-allowed"
62
+ >
57
63
  <slot v-if="$slots.item" name="item" v-bind="{ item, close }" />
58
64
  <component
59
65
  v-else-if="item.component"
@@ -160,6 +166,8 @@
160
166
  (event: PointerEvent) =>
161
167
  handleItemClick(subItem, event)
162
168
  "
169
+ :disabled="subItem.disabled"
170
+ class="data-[disabled]:cursor-not-allowed"
163
171
  >
164
172
  <component
165
173
  v-if="subItem.component"
@@ -310,10 +318,16 @@ const normalizeDropdownItem = (option: DropdownOption) => {
310
318
  }
311
319
  }
312
320
 
313
- const getIconColor = (item: DropdownItem) =>
314
- item.theme === 'red' ? 'text-ink-red-3' : 'text-ink-gray-6'
315
- const getTextColor = (item: DropdownItem) =>
316
- item.theme === 'red' ? 'text-ink-red-3' : 'text-ink-gray-7'
321
+ const getIconColor = (item: DropdownItem) => {
322
+ if (item.disabled) return 'text-ink-gray-4'
323
+ return item.theme === 'red' ? 'text-ink-red-3' : 'text-ink-gray-6'
324
+ }
325
+
326
+ const getTextColor = (item: DropdownItem) => {
327
+ if (item.disabled) return 'text-ink-gray-4'
328
+ return item.theme === 'red' ? 'text-ink-red-3' : 'text-ink-gray-7'
329
+ }
330
+
317
331
  const getBackgroundColor = (item: DropdownItem) =>
318
332
  item.theme === 'red'
319
333
  ? 'focus:bg-surface-red-3 data-[highlighted]:bg-surface-red-3 data-[state=open]:bg-surface-red-3'
@@ -6,6 +6,7 @@ export type DropdownOption = {
6
6
  label: string
7
7
  icon?: string | Component | null
8
8
  switch?: boolean
9
+ disabled?: boolean
9
10
  switchValue?: boolean
10
11
  theme?: 'gray' | 'red'
11
12
  component?: any
@@ -26,7 +26,7 @@
26
26
  </template>
27
27
  <script setup>
28
28
  import { inject } from 'vue'
29
- import DownSolid from '../../icons/DownSolid.vue'
29
+ import DownSolid from '../../../icons/DownSolidIcon.vue'
30
30
 
31
31
  const props = defineProps({
32
32
  group: {
@@ -2,6 +2,11 @@
2
2
  <div class="mb-5 mt-2" v-if="!group.collapsed">
3
3
  <slot>
4
4
  <ListRow v-for="row in group.rows" :key="row[list.rowKey]" :row="row" />
5
+ <component
6
+ v-if="list.slots['group-empty'] && group.rows.length == 0"
7
+ :is="list.slots['group-empty']"
8
+ v-bind="{ group }"
9
+ />
5
10
  </slot>
6
11
  </div>
7
12
  </template>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
3
  import Select from './Select.vue'
4
+ import LucideUser from '~icons/lucide/user'
4
5
 
5
6
  const value = ref('')
6
7
  const options = [
@@ -14,8 +15,20 @@ const options = [
14
15
  </script>
15
16
  <template>
16
17
  <Story :layout="{ width: 500, type: 'grid' }">
17
- <div class="p-2">
18
- <Select :options="options" v-model="value" />
19
- </div>
18
+ <Variant title="Default">
19
+ <div class="p-2">
20
+ <Select :options="options" v-model="value" />
21
+ </div>
22
+ </Variant>
23
+
24
+ <Variant title="With prefix">
25
+ <div class="p-2">
26
+ <Select :options="options" v-model="value">
27
+ <template #prefix>
28
+ <LucideUser class="size-4 text-ink-gray-9" />
29
+ </template>
30
+ </Select>
31
+ </div>
32
+ </Variant>
20
33
  </Story>
21
34
  </template>
@@ -1,83 +1,25 @@
1
- <template>
2
- <div class="relative flex items-center">
3
- <div
4
- :class="[
5
- 'absolute inset-y-0 left-0 flex items-center',
6
- textColor,
7
- prefixClasses,
8
- ]"
9
- v-if="$slots.prefix"
10
- >
11
- <slot name="prefix"> </slot>
12
- </div>
13
- <div
14
- v-if="placeholder"
15
- v-show="!modelValue"
16
- class="pointer-events-none absolute text-ink-gray-4 truncate w-full"
17
- :class="[fontSizeClasses, paddingClasses]"
18
- >
19
- {{ placeholder }}
20
- </div>
21
- <select
22
- :class="selectClasses"
23
- :disabled="disabled"
24
- :id="id"
25
- :value="modelValue"
26
- @change="handleChange"
27
- v-bind="attrs"
28
- >
29
- <option
30
- v-for="option in selectOptions"
31
- :key="option.value"
32
- :value="option.value"
33
- :disabled="option.disabled || false"
34
- :selected="modelValue === option.value"
35
- >
36
- {{ option.label }}
37
- </option>
38
- </select>
39
- </div>
40
- </template>
41
-
42
1
  <script setup lang="ts">
43
- import { computed, useSlots, useAttrs } from 'vue'
2
+ import { computed } from 'vue'
44
3
  import type { SelectProps } from './types'
4
+ import LucideChevronDown from '~icons/lucide/chevron-down'
45
5
 
46
- defineOptions({
47
- inheritAttrs: false,
48
- })
6
+ import {
7
+ SelectContent,
8
+ SelectItem,
9
+ SelectItemText,
10
+ SelectPortal,
11
+ SelectRoot,
12
+ SelectTrigger,
13
+ SelectValue,
14
+ SelectViewport,
15
+ } from 'reka-ui'
16
+
17
+ const model = defineModel<String>()
49
18
 
50
19
  const props = withDefaults(defineProps<SelectProps>(), {
51
20
  size: 'sm',
52
21
  variant: 'subtle',
53
- })
54
-
55
- const emit = defineEmits(['update:modelValue'])
56
- const slots = useSlots()
57
- const attrs = useAttrs()
58
-
59
- function handleChange(e: Event) {
60
- emit('update:modelValue', (e.target as HTMLInputElement).value)
61
- }
62
-
63
- const selectOptions = computed(() => {
64
- return (
65
- props.options
66
- ?.map((option) => {
67
- if (typeof option === 'string') {
68
- return {
69
- label: option,
70
- value: option,
71
- }
72
- }
73
- return option
74
- })
75
- .filter(Boolean) || []
76
- )
77
- })
78
-
79
- const textColor = computed(() => {
80
- return props.disabled ? 'text-ink-gray-5' : 'text-ink-gray-8'
22
+ placeholder: 'Select option',
81
23
  })
82
24
 
83
25
  const fontSizeClasses = computed(() => {
@@ -91,29 +33,29 @@ const fontSizeClasses = computed(() => {
91
33
 
92
34
  const paddingClasses = computed(() => {
93
35
  return {
94
- sm: 'pl-2 pr-5',
95
- md: 'pl-2.5 pr-5.5',
96
- lg: 'pl-3 pr-6',
97
- xl: 'pl-3 pr-6',
36
+ sm: 'px-2',
37
+ md: 'px-2.5 ',
38
+ lg: 'px-3',
39
+ xl: 'px-3',
98
40
  }[props.size]
99
41
  })
100
42
 
101
- const selectClasses = computed(() => {
102
- let sizeClasses = {
103
- sm: 'rounded h-7',
104
- md: 'rounded h-8',
105
- lg: 'rounded-md h-10',
106
- xl: 'rounded-md h-10',
107
- }[props.size]
43
+ let sizeClasses = {
44
+ sm: 'rounded min-h-7',
45
+ md: 'rounded min-h-8',
46
+ lg: 'rounded-md min-h-10',
47
+ xl: 'rounded-md min-h-10',
48
+ }[props.size]
108
49
 
50
+ const selectClasses = computed(() => {
109
51
  let variant = props.disabled ? 'disabled' : props.variant
110
52
  let variantClasses = {
111
53
  subtle:
112
- 'border border-[--surface-gray-2] bg-surface-gray-2 hover:border-outline-gray-modals hover:bg-surface-gray-3 focus:border-outline-gray-4 focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3',
54
+ 'border border-[--surface-gray-2] bg-surface-gray-2 hover:border-outline-gray-modals hover:bg-surface-gray-3',
113
55
  outline:
114
- 'border border-outline-gray-2 bg-surface-white hover:border-outline-gray-3 focus:border-outline-gray-4 focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3',
56
+ 'border border-outline-gray-2 bg-surface-white hover:border-outline-gray-3',
115
57
  ghost:
116
- 'bg-transparent border-transparent hover:bg-surface-gray-3 focus:bg-surface-gray-3 focus:border-outline-gray-4 focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3',
58
+ 'bg-transparent border-transparent hover:bg-surface-gray-3 focus:bg-surface-gray-3',
117
59
  disabled: [
118
60
  'border',
119
61
  props.variant !== 'ghost' ? 'bg-surface-gray-1' : '',
@@ -128,17 +70,88 @@ const selectClasses = computed(() => {
128
70
  fontSizeClasses.value,
129
71
  paddingClasses.value,
130
72
  variantClasses,
131
- textColor.value,
132
- 'transition-colors w-full py-0 truncate',
73
+ 'transition-colors w-full data-[state=open]:ring-2 ring-outline-gray-2 ',
133
74
  ]
134
75
  })
135
76
 
136
- let prefixClasses = computed(() => {
137
- return {
138
- sm: 'pl-2',
139
- md: 'pl-2.5',
140
- lg: 'pl-3',
141
- xl: 'pl-3',
142
- }[props.size]
77
+ const selectOptions = computed(() => {
78
+ const str = typeof props.options?.[0] == 'string'
79
+ const tmp = props.options?.map((x) => ({ label: x, value: x }))
80
+ return (str ? tmp : props.options)?.filter(Boolean) || []
143
81
  })
144
82
  </script>
83
+
84
+ <template>
85
+ <SelectRoot v-model="model">
86
+ <SelectTrigger
87
+ class="inline-flex items-center gap-2 outline-none text-base data-[placeholder]:text-ink-gray-4 data-[disabled]:text-ink-gray-4"
88
+ aria-label="Customise options"
89
+ :class="selectClasses"
90
+ :disabled="props.disabled"
91
+ >
92
+ <slot name="prefix" />
93
+ <SelectValue :placeholder="props.placeholder" />
94
+ <LucideChevronDown class="size-4 text-ink-gray-4 ml-auto" />
95
+ </SelectTrigger>
96
+
97
+ <SelectPortal>
98
+ <SelectContent
99
+ class="bg-surface-modal border rounded-lg shadow-lg will-change-[opacity,transform] z-[100] min-w-[--reka-select-trigger-width] max-h-[--reka-select-content-available-height] overflow-auto"
100
+ :side-offset="5"
101
+ position="popper"
102
+ >
103
+ <SelectViewport class="p-1 flex flex-col">
104
+ <SelectItem
105
+ v-for="(option, index) in selectOptions"
106
+ :disabled="option.disabled"
107
+ :key="index"
108
+ :value="option.value"
109
+ :class="[sizeClasses, paddingClasses, fontSizeClasses]"
110
+ class="text-base text-ink-gray-9 flex items-center relative data-[highlighted]:bg-surface-gray-2 border-0 [data-state=checked]:bg-surface-gray-2 data-[disabled]:text-ink-gray-4"
111
+ >
112
+ <SelectItemText>
113
+ {{ option.label }}
114
+ </SelectItemText>
115
+ </SelectItem>
116
+ </SelectViewport>
117
+ </SelectContent>
118
+ </SelectPortal>
119
+ </SelectRoot>
120
+ </template>
121
+
122
+ <style>
123
+ @keyframes slideDownFade {
124
+ from {
125
+ opacity: 0;
126
+ transform: translateY(-4px) scale(0.98);
127
+ }
128
+ to {
129
+ opacity: 1;
130
+ transform: translateY(0) scale(1);
131
+ }
132
+ }
133
+
134
+ @keyframes slideUpFade {
135
+ from {
136
+ opacity: 0;
137
+ transform: translateY(4px) scale(0.98);
138
+ }
139
+ to {
140
+ opacity: 1;
141
+ transform: translateY(0) scale(1);
142
+ }
143
+ }
144
+
145
+ [data-side='top'] {
146
+ animation: slideDownFade 280ms;
147
+ }
148
+
149
+ [data-side='bottom'] {
150
+ animation: slideUpFade 280ms;
151
+ }
152
+
153
+ [data-highlighted],
154
+ [data-state='checked'] {
155
+ outline: none !important;
156
+ }
157
+ </style>
@@ -1,2 +1,5 @@
1
1
  export { default as Sidebar } from './Sidebar.vue'
2
+ export { default as SidebarHeader } from './SidebarHeader.vue'
3
+ export { default as SidebarItem } from './SidebarItem.vue'
4
+ export { default as SidebarSection } from './SidebarSection.vue'
2
5
  export type { SidebarProps } from './types'
@@ -56,7 +56,7 @@ import { ToastAction, ToastClose, ToastDescription, ToastRoot } from 'reka-ui'
56
56
  import LucideInfo from '~icons/lucide/info'
57
57
  import LucideAlertTriangle from '~icons/lucide/alert-triangle'
58
58
  import LucideX from '~icons/lucide/x'
59
- import CircleCheck from '../../icons/CircleCheck.vue'
59
+ import CircleCheck from '../../../icons/CircleCheckIcon.vue'
60
60
  import type { ToastProps } from './types'
61
61
 
62
62
  const props = defineProps<ToastProps>()
@@ -1,6 +1,8 @@
1
+ export * from './useCall/types'
1
2
  export { useCall } from './useCall/useCall'
2
- export { useList } from './useList/useList'
3
3
  export { useDoc } from './useDoc/useDoc'
4
4
  export { useDoctype } from './useDoctype/useDoctype'
5
- export { useNewDoc } from './useNewDoc/useNewDoc'
6
5
  export { useFrappeFetch } from './useFrappeFetch'
6
+ export * from './useList/types'
7
+ export { useList } from './useList/useList'
8
+ export { useNewDoc } from './useNewDoc/useNewDoc'
package/src/index.ts CHANGED
@@ -9,9 +9,7 @@ export * from './components/Button'
9
9
  export { default as Card } from './components/Card.vue'
10
10
  export * from './components/Combobox'
11
11
  export * from './components/Checkbox'
12
- export { default as DatePicker } from './components/DatePicker/DatePicker.vue'
13
- export { default as DateTimePicker } from './components/DatePicker/DateTimePicker.vue'
14
- export { default as DateRangePicker } from './components/DatePicker/DateRangePicker.vue'
12
+ export * from './components/DatePicker'
15
13
  export * from './components/Dialog'
16
14
  export { default as Dialogs } from './components/Dialogs.vue'
17
15
  export * from './components/Divider'
@@ -21,7 +19,6 @@ export { default as FeatherIcon } from './components/FeatherIcon.vue'
21
19
  export * from './components/FileUploader'
22
20
  export * from './components/FormControl'
23
21
  export { default as FormLabel } from './components/FormLabel.vue'
24
- export { default as GreenCheckIcon } from './components/GreenCheckIcon.vue'
25
22
  export { default as Input } from './components/Input.vue'
26
23
  export { default as ListItem } from './components/ListItem.vue'
27
24
  export { default as LoadingIndicator } from './components/LoadingIndicator.vue'
@@ -67,7 +64,9 @@ export * from './components/Calendar'
67
64
  export * from './components/CircularProgressBar'
68
65
  export * from './components/Tree'
69
66
  export { default as FrappeUIProvider } from './components/Provider/FrappeUIProvider.vue'
70
- export { default as Sidebar } from './components/Sidebar/Sidebar.vue'
67
+ export * from './components/Sidebar/index.ts'
68
+ export { default as ConfirmDialog } from './components/ConfirmDialog.vue'
69
+
71
70
 
72
71
  // grid layout
73
72
  export { default as GridLayout } from './components/VueGridLayout/Layout.vue'
@@ -92,33 +91,20 @@ export { usePageMeta } from './utils/pageMeta'
92
91
  export { dayjsLocal, dayjs } from './utils/dayjs'
93
92
  export * from './utils/useFileUpload'
94
93
  export * from './utils/theme'
94
+ export * from './components/TextEditor/extensions/image'
95
95
 
96
96
  // old data-fetching: resources
97
- export {
98
- createResource,
99
- createDocumentResource,
100
- createListResource,
101
- getCachedResource,
102
- getCachedDocumentResource,
103
- getCachedListResource,
104
- resourcesPlugin,
105
- } from './resources/index.js'
97
+ export * from './resources/index.ts'
98
+
106
99
  export { request } from './utils/request.js'
107
100
  export { frappeRequest } from './utils/frappeRequest.js'
108
101
  export { default as initSocket } from './utils/socketio.js'
109
102
  export { setConfig, getConfig } from './utils/config'
110
103
 
111
104
  // new data-fetching composables
112
- export {
113
- useCall,
114
- useList,
115
- useDoc,
116
- useNewDoc,
117
- useDoctype,
118
- useFrappeFetch,
119
- } from './data-fetching'
105
+ export * from './data-fetching'
120
106
 
121
107
  // plugin
108
+ export { confirmDialog } from './utils/confirmDialog.js'
122
109
  export { default as pageMetaPlugin } from './utils/pageMeta.js'
123
110
  export { default as FrappeUI } from './utils/plugin.js'
124
- export { confirmDialog } from './utils/confirmDialog.js'
@@ -1,7 +1,9 @@
1
- export { createResource, getCachedResource } from './resources'
2
1
  export {
3
2
  createDocumentResource,
4
3
  getCachedDocumentResource,
5
4
  } from './documentResource'
6
5
  export { createListResource, getCachedListResource } from './listResource'
6
+ export * from './local'
7
7
  export { default as resourcesPlugin } from './plugin'
8
+ export * from './realtime'
9
+ export { createResource, getCachedResource } from './resources'
@@ -1,6 +1,6 @@
1
- import { get, set, del } from 'idb-keyval'
1
+ import { del, get, set } from 'idb-keyval'
2
2
 
3
- export function saveLocal(key, data) {
3
+ export function saveLocal<T = any>(key: string, data: T): Promise<void | null> {
4
4
  if (typeof indexedDB === 'undefined') {
5
5
  return Promise.resolve(null)
6
6
  }
@@ -8,7 +8,7 @@ export function saveLocal(key, data) {
8
8
  return set(key, JSON.stringify(data))
9
9
  }
10
10
 
11
- export function deleteLocal(key) {
11
+ export function deleteLocal(key: string): Promise<void | null> {
12
12
  if (typeof indexedDB === 'undefined') {
13
13
  return Promise.resolve(null)
14
14
  }
@@ -16,7 +16,7 @@ export function deleteLocal(key) {
16
16
  return del(key)
17
17
  }
18
18
 
19
- export function getLocal(key) {
19
+ export function getLocal<T = any>(key: string): Promise<T | null> {
20
20
  if (typeof indexedDB === 'undefined') {
21
21
  return Promise.resolve(null)
22
22
  }
@@ -0,0 +1,21 @@
1
+ import { Socket } from 'socket.io-client'
2
+
3
+ export function onDocUpdate(
4
+ socket: Socket,
5
+ doctype: string,
6
+ callback: (name: string) => void,
7
+ ): void {
8
+ subscribe(socket, doctype)
9
+ socket.on('list_update', (data) => {
10
+ if (data.doctype == doctype) {
11
+ callback(data.name)
12
+ }
13
+ })
14
+ }
15
+
16
+ let subscribed: Record<string, boolean> = {}
17
+ function subscribe(socket: Socket, doctype: string): void {
18
+ if (subscribed[doctype]) return
19
+ socket.emit('doctype_subscribe', doctype)
20
+ subscribed[doctype] = true
21
+ }
@@ -1,16 +0,0 @@
1
- <template>
2
- <svg
3
- width="16"
4
- height="16"
5
- viewBox="0 0 16 16"
6
- fill="none"
7
- xmlns="http://www.w3.org/2000/svg"
8
- >
9
- <path
10
- fill-rule="evenodd"
11
- clip-rule="evenodd"
12
- d="M14.25 8C14.25 11.4518 11.4518 14.25 8 14.25C4.54822 14.25 1.75 11.4518 1.75 8C1.75 4.54822 4.54822 1.75 8 1.75C11.4518 1.75 14.25 4.54822 14.25 8ZM15.25 8C15.25 12.0041 12.0041 15.25 8 15.25C3.99594 15.25 0.75 12.0041 0.75 8C0.75 3.99594 3.99594 0.75 8 0.75C12.0041 0.75 15.25 3.99594 15.25 8ZM7.37988 9.37695V9.44531H8.39062V9.37695C8.39062 9.10352 8.41992 8.88542 8.47852 8.72266C8.53711 8.55664 8.62826 8.41504 8.75195 8.29785C8.87891 8.18066 9.04329 8.06185 9.24512 7.94141C9.56087 7.74609 9.8099 7.51009 9.99219 7.2334C10.1745 6.95345 10.2656 6.61328 10.2656 6.21289C10.2656 5.82878 10.1745 5.49186 9.99219 5.20215C9.81315 4.91244 9.56087 4.6862 9.23535 4.52344C8.90983 4.36068 8.52734 4.2793 8.08789 4.2793C7.69401 4.2793 7.33268 4.35579 7.00391 4.50879C6.67513 4.65853 6.41146 4.88151 6.21289 5.17773C6.01432 5.4707 5.90853 5.82878 5.89551 6.25195H6.96973C6.986 6.0013 7.04948 5.79785 7.16016 5.6416C7.27083 5.4821 7.40755 5.36491 7.57031 5.29004C7.73633 5.21517 7.90885 5.17773 8.08789 5.17773C8.28971 5.17773 8.47363 5.22005 8.63965 5.30469C8.80892 5.38932 8.94075 5.50814 9.03516 5.66113C9.13281 5.81413 9.18164 5.99479 9.18164 6.20312C9.18164 6.47005 9.11003 6.69954 8.9668 6.8916C8.82357 7.0804 8.64453 7.23828 8.42969 7.36523C8.21159 7.50195 8.02279 7.64193 7.86328 7.78516C7.70703 7.92513 7.58659 8.11556 7.50195 8.35645C7.42057 8.59408 7.37988 8.93425 7.37988 9.37695ZM7.37988 11.5205C7.51986 11.654 7.69076 11.7207 7.89258 11.7207C8.09766 11.7207 8.26855 11.654 8.40527 11.5205C8.54525 11.3838 8.61523 11.2161 8.61523 11.0176C8.61523 10.8158 8.54525 10.6481 8.40527 10.5146C8.26855 10.3779 8.09766 10.3096 7.89258 10.3096C7.69076 10.3096 7.51986 10.3779 7.37988 10.5146C7.24316 10.6481 7.1748 10.8158 7.1748 11.0176C7.1748 11.2161 7.24316 11.3838 7.37988 11.5205Z"
13
- fill="currentColor"
14
- />
15
- </svg>
16
- </template>
@@ -1,16 +0,0 @@
1
- <template>
2
- <svg
3
- width="17"
4
- height="16"
5
- viewBox="0 0 17 16"
6
- fill="none"
7
- xmlns="http://www.w3.org/2000/svg"
8
- >
9
- <path
10
- fill-rule="evenodd"
11
- clip-rule="evenodd"
12
- d="M6.2641 1C5.5758 1 4.97583 1.46845 4.80889 2.1362L3.57555 7.06953C3.33887 8.01625 4.05491 8.93333 5.03077 8.93333H7.50682L6.72168 14.4293C6.68838 14.6624 6.82229 14.8872 7.04319 14.9689C7.26408 15.0507 7.51204 14.9671 7.63849 14.7684L13.2161 6.00354C13.6398 5.33782 13.1616 4.46667 12.3725 4.46667H9.59038L10.3017 1.62127C10.3391 1.4719 10.3055 1.31365 10.2108 1.19229C10.116 1.07094 9.97063 1 9.81666 1H6.2641ZM5.77903 2.37873C5.83468 2.15615 6.03467 2 6.2641 2H9.17627L8.46492 4.8454C8.42758 4.99477 8.46114 5.15302 8.55589 5.27437C8.65064 5.39573 8.79602 5.46667 8.94999 5.46667H12.3725L8.0395 12.2757L8.5783 8.50404C8.5988 8.36056 8.55602 8.21523 8.46105 8.10573C8.36608 7.99623 8.22827 7.93333 8.08332 7.93333H5.03077C4.70548 7.93333 4.4668 7.62764 4.5457 7.31207L5.77903 2.37873Z"
13
- fill="currentColor"
14
- />
15
- </svg>
16
- </template>
@@ -1,19 +0,0 @@
1
- <template>
2
- <svg
3
- xmlns="http://www.w3.org/2000/svg"
4
- width="16"
5
- height="16"
6
- viewBox="0 0 24 24"
7
- fill="none"
8
- stroke="currentColor"
9
- stroke-width="1.5"
10
- stroke-linecap="round"
11
- stroke-linejoin="round"
12
- class="feather feather-maximize-2"
13
- >
14
- <polyline points="15 3 21 3 21 9" />
15
- <polyline points="9 21 3 21 3 15" />
16
- <line x1="21" y1="3" x2="14" y2="10" />
17
- <line x1="3" y1="21" x2="10" y2="14" />
18
- </svg>
19
- </template>
@@ -1,19 +0,0 @@
1
- <template>
2
- <svg
3
- xmlns="http://www.w3.org/2000/svg"
4
- width="16"
5
- height="16"
6
- viewBox="0 0 24 24"
7
- fill="none"
8
- stroke="currentColor"
9
- stroke-width="1.5"
10
- stroke-linecap="round"
11
- stroke-linejoin="round"
12
- class="feather feather-minimize-2"
13
- >
14
- <polyline points="4 14 10 14 10 20" />
15
- <polyline points="20 10 14 10 14 4" />
16
- <line x1="14" y1="10" x2="21" y2="3" />
17
- <line x1="3" y1="21" x2="10" y2="14" />
18
- </svg>
19
- </template>
@@ -1,16 +0,0 @@
1
- <template>
2
- <svg
3
- width="16"
4
- height="16"
5
- viewBox="0 0 16 16"
6
- fill="none"
7
- xmlns="http://www.w3.org/2000/svg"
8
- >
9
- <path
10
- fill-rule="evenodd"
11
- clip-rule="evenodd"
12
- d="M8 6.5C9.10457 6.5 10 5.60457 10 4.5C10 3.39543 9.10457 2.5 8 2.5C6.89543 2.5 6 3.39543 6 4.5C6 5.60457 6.89543 6.5 8 6.5ZM8 7.5C9.65685 7.5 11 6.15685 11 4.5C11 2.84315 9.65685 1.5 8 1.5C6.34315 1.5 5 2.84315 5 4.5C5 6.15685 6.34315 7.5 8 7.5ZM12 13.5C13.1046 13.5 14 12.6046 14 11.5C14 10.3954 13.1046 9.5 12 9.5C10.8954 9.5 10 10.3954 10 11.5C10 12.6046 10.8954 13.5 12 13.5ZM12 14.5C13.6569 14.5 15 13.1569 15 11.5C15 9.84315 13.6569 8.5 12 8.5C10.3431 8.5 9 9.84315 9 11.5C9 13.1569 10.3431 14.5 12 14.5ZM6 11.5C6 12.6046 5.10457 13.5 4 13.5C2.89543 13.5 2 12.6046 2 11.5C2 10.3954 2.89543 9.5 4 9.5C5.10457 9.5 6 10.3954 6 11.5ZM7 11.5C7 13.1569 5.65685 14.5 4 14.5C2.34315 14.5 1 13.1569 1 11.5C1 9.84315 2.34315 8.5 4 8.5C5.65685 8.5 7 9.84315 7 11.5Z"
13
- fill="currentColor"
14
- />
15
- </svg>
16
- </template>
@@ -1,16 +0,0 @@
1
- <template>
2
- <svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
3
- <path
4
- d="M16 32c8.837 0 16-7.163 16-16S24.837 0 16 0 0 7.163 0 16s7.163 16 16 16z"
5
- fill="#59B179"
6
- />
7
- <path
8
- d="M9.333 17.227l1.333 1.333 2.667 2.667 5.333-5.333 2.667-2.667 1.333-1.333"
9
- stroke="#fff"
10
- stroke-width="2"
11
- stroke-miterlimit="10"
12
- stroke-linecap="round"
13
- stroke-linejoin="round"
14
- />
15
- </svg>
16
- </template>
@@ -1,9 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16">
3
- <path
4
- fill="currentColor"
5
- d="M8 .75a7.25 7.25 0 1 1 0 14.5A7.25 7.25 0 0 1 8 .75Zm0 1a6.25 6.25 0 1 0 0 12.5 6.25 6.25 0 0 0 0-12.5Zm2.59 3.527a.501.501 0 0 1 .758.623l-.057.085-3.848 4.666a.501.501 0 0 1-.78-.011L4.936 8.41l-.053-.086a.501.501 0 0 1 .775-.6l.07.074 1.34 1.733 3.45-4.183.072-.072Z"
6
- />
7
- </svg>
8
- </template>
9
- <script setup lang="ts"></script>
@@ -1,8 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16">
3
- <path
4
- fill="currentColor"
5
- d="M4.293 5.28h7.413a.5.5 0 0 1 .41.787l-3.707 5.295a.5.5 0 0 1-.82 0L3.884 6.067a.5.5 0 0 1 .41-.787Z"
6
- />
7
- </svg>
8
- </template>
@@ -1,15 +0,0 @@
1
- export function onDocUpdate(socket, doctype, callback) {
2
- subscribe(socket, doctype)
3
- socket.on('list_update', (data) => {
4
- if (data.doctype == doctype) {
5
- callback(data.name)
6
- }
7
- })
8
- }
9
-
10
- let subscribed = {}
11
- function subscribe(socket, doctype) {
12
- if (subscribed[doctype]) return
13
- socket.emit('doctype_subscribe', doctype)
14
- subscribed[doctype] = true
15
- }