pimelon-ui 0.1.198 → 0.1.201
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/package.json +1 -1
- package/src/components/Combobox/Combobox.vue +7 -1
- package/src/components/Combobox/types.ts +1 -0
- package/src/components/DatePicker/DatePicker.vue +12 -9
- package/src/components/DatePicker/DateTimePicker.vue +16 -10
- package/src/components/Dialog/Dialog.vue +1 -1
- package/src/components/ListView/ListEmptyState.vue +1 -1
- package/src/components/Sidebar/SidebarItem.vue +1 -1
- package/src/components/TextEditor/TextEditor.vue +3 -0
- package/src/components/TextEditor/extensions/iframe/IframeNodeView.vue +4 -2
- package/src/components/TextEditor/extensions/iframe/iframe-extension.ts +10 -1
- package/src/components/TextEditor/extensions/iframe/utils.ts +1 -0
- package/src/components/TextEditor/types.ts +1 -0
- package/src/resources/documentResource.js +3 -0
- package/vite/melonProxy.js +1 -1
package/package.json
CHANGED
|
@@ -53,6 +53,12 @@ watch(
|
|
|
53
53
|
searchTerm.value = getDisplayValue(newValue)
|
|
54
54
|
},
|
|
55
55
|
)
|
|
56
|
+
watch(
|
|
57
|
+
() => getDisplayValue(props.modelValue),
|
|
58
|
+
(newDisplay) => {
|
|
59
|
+
if (!userHasTyped.value) searchTerm.value = newDisplay
|
|
60
|
+
},
|
|
61
|
+
)
|
|
56
62
|
|
|
57
63
|
const onUpdateModelValue = (value: string | null) => {
|
|
58
64
|
const selectedOpt = value
|
|
@@ -311,7 +317,7 @@ defineExpose({
|
|
|
311
317
|
position="popper"
|
|
312
318
|
@openAutoFocus.prevent
|
|
313
319
|
@closeAutoFocus.prevent
|
|
314
|
-
:align="'start'"
|
|
320
|
+
:align="props.placement || 'start'"
|
|
315
321
|
>
|
|
316
322
|
<ComboboxViewport
|
|
317
323
|
class="max-h-60 overflow-auto pb-1.5"
|
|
@@ -202,6 +202,7 @@ import { ref, computed, watch, toRefs } from 'vue'
|
|
|
202
202
|
import { Popover } from '../Popover'
|
|
203
203
|
import { Button } from '../Button'
|
|
204
204
|
import { TextInput } from '../TextInput'
|
|
205
|
+
// @ts-ignore - Vue SFC without explicit types
|
|
205
206
|
import FeatherIcon from '../FeatherIcon.vue'
|
|
206
207
|
import { dayjs, dayjsLocal } from '../../utils/dayjs'
|
|
207
208
|
import { months, monthStart, generateWeeks, getDateValue } from './utils'
|
|
@@ -235,7 +236,7 @@ const currentMonth = ref<number>(dayjs().month()) // 0-index
|
|
|
235
236
|
const DATE_FORMAT = 'YYYY-MM-DD'
|
|
236
237
|
|
|
237
238
|
const selected = ref<string>('')
|
|
238
|
-
const initialValue = props.modelValue || props.value || ''
|
|
239
|
+
const initialValue = ref(props.modelValue || props.value || '')
|
|
239
240
|
|
|
240
241
|
function coerceToDayjs(val?: string | null): Dayjs | null {
|
|
241
242
|
if (!val) return null
|
|
@@ -277,7 +278,7 @@ function syncFromValue(val?: string): void {
|
|
|
277
278
|
selected.value = d.format(DATE_FORMAT)
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
syncFromValue(initialValue)
|
|
281
|
+
syncFromValue(initialValue.value)
|
|
281
282
|
|
|
282
283
|
function initFromValue(): void {
|
|
283
284
|
syncFromValue(props.modelValue || props.value)
|
|
@@ -308,10 +309,6 @@ watch(displayLabel, (val) => {
|
|
|
308
309
|
if (!isTyping.value) inputValue.value = val
|
|
309
310
|
})
|
|
310
311
|
|
|
311
|
-
function parseInput(val: string): Dayjs | null {
|
|
312
|
-
return coerceToDayjs(val)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
312
|
function maybeClose(togglePopover?: () => void, condition = true) {
|
|
316
313
|
if (condition && autoClose.value && togglePopover) togglePopover()
|
|
317
314
|
}
|
|
@@ -321,6 +318,7 @@ function clearSelection() {
|
|
|
321
318
|
selected.value = ''
|
|
322
319
|
emit('update:modelValue', '')
|
|
323
320
|
emit('change', '')
|
|
321
|
+
initialValue.value = ''
|
|
324
322
|
inputValue.value = ''
|
|
325
323
|
}
|
|
326
324
|
|
|
@@ -336,7 +334,7 @@ function commitInput(close = false, togglePopover?: () => void): void {
|
|
|
336
334
|
}
|
|
337
335
|
return
|
|
338
336
|
}
|
|
339
|
-
const d =
|
|
337
|
+
const d = coerceToDayjs(raw)
|
|
340
338
|
if (d) {
|
|
341
339
|
selectDate(d)
|
|
342
340
|
maybeClose(togglePopover, close)
|
|
@@ -370,8 +368,13 @@ function selectDate(date: string | Date | Dayjs): void {
|
|
|
370
368
|
selected.value = d.format(DATE_FORMAT)
|
|
371
369
|
currentYear.value = d.year()
|
|
372
370
|
currentMonth.value = d.month()
|
|
373
|
-
|
|
374
|
-
if (selected.value !==
|
|
371
|
+
|
|
372
|
+
if (selected.value !== initialValue.value) {
|
|
373
|
+
emit('update:modelValue', selected.value)
|
|
374
|
+
if (selected.value !== prev) emit('change', selected.value)
|
|
375
|
+
initialValue.value = selected.value
|
|
376
|
+
}
|
|
377
|
+
|
|
375
378
|
// Reflect new value in input immediately if not typing
|
|
376
379
|
if (!isTyping.value) {
|
|
377
380
|
inputValue.value = props.format
|
|
@@ -273,7 +273,7 @@ const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
|
|
|
273
273
|
const selectedDate = ref<string>('') // YYYY-MM-DD
|
|
274
274
|
const timeValue = ref<string>('') // HH:mm:ss
|
|
275
275
|
|
|
276
|
-
const initialValue = props.modelValue || props.value || ''
|
|
276
|
+
const initialValue = ref(props.modelValue || props.value || '')
|
|
277
277
|
|
|
278
278
|
function coerceDateTime(val?: string | null): Dayjs | null {
|
|
279
279
|
if (!val) return null
|
|
@@ -285,12 +285,12 @@ function coerceDateTime(val?: string | null): Dayjs | null {
|
|
|
285
285
|
if (dStrict.isValid()) return dStrict
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
const dLoose =
|
|
288
|
+
const dLoose = dayjsLocal(raw)
|
|
289
289
|
if (dLoose.isValid()) return dLoose
|
|
290
290
|
|
|
291
291
|
const normalized = getDateValue(raw)
|
|
292
292
|
if (normalized) {
|
|
293
|
-
const dNorm =
|
|
293
|
+
const dNorm = dayjsLocal(normalized)
|
|
294
294
|
if (dNorm.isValid()) return dNorm
|
|
295
295
|
}
|
|
296
296
|
return null
|
|
@@ -322,7 +322,7 @@ function syncFromValue(val?: string): void {
|
|
|
322
322
|
timeValue.value = d.format('HH:mm:ss')
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
syncFromValue(initialValue)
|
|
325
|
+
syncFromValue(initialValue.value)
|
|
326
326
|
|
|
327
327
|
function initFromValue(): void {
|
|
328
328
|
syncFromValue(props.modelValue || props.value)
|
|
@@ -339,10 +339,9 @@ watch(
|
|
|
339
339
|
const combinedValue = computed<string>(() => {
|
|
340
340
|
if (!selectedDate.value) return ''
|
|
341
341
|
const base = `${selectedDate.value} ${timeValue.value || '00:00:00'}`
|
|
342
|
-
const local =
|
|
342
|
+
const local = dayjs(base)
|
|
343
343
|
if (!local.isValid()) return ''
|
|
344
|
-
|
|
345
|
-
return sys.format(DATE_TIME_FORMAT)
|
|
344
|
+
return local.format(DATE_TIME_FORMAT)
|
|
346
345
|
})
|
|
347
346
|
|
|
348
347
|
const displayLabel = computed<string>(() => {
|
|
@@ -367,6 +366,7 @@ function clearSelection() {
|
|
|
367
366
|
timeValue.value = ''
|
|
368
367
|
emit('update:modelValue', '')
|
|
369
368
|
emit('change', '')
|
|
369
|
+
initialValue.value = ''
|
|
370
370
|
inputValue.value = ''
|
|
371
371
|
}
|
|
372
372
|
|
|
@@ -512,10 +512,16 @@ function emitChange(close = false, togglePopover?: () => void) {
|
|
|
512
512
|
clearSelection()
|
|
513
513
|
return
|
|
514
514
|
}
|
|
515
|
-
const out = combinedValue.value
|
|
516
515
|
|
|
517
|
-
|
|
518
|
-
|
|
516
|
+
const localDateTime = combinedValue.value
|
|
517
|
+
const systemDateTime = dayjsSystem(localDateTime).format(DATE_TIME_FORMAT)
|
|
518
|
+
|
|
519
|
+
if (systemDateTime !== initialValue.value) {
|
|
520
|
+
emit('update:modelValue', systemDateTime)
|
|
521
|
+
emit('change', systemDateTime)
|
|
522
|
+
initialValue.value = systemDateTime
|
|
523
|
+
}
|
|
524
|
+
|
|
519
525
|
if (!isTyping.value) inputValue.value = displayLabel.value
|
|
520
526
|
maybeClose(togglePopover, close)
|
|
521
527
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
:class="dialogPositionClasses"
|
|
12
12
|
>
|
|
13
13
|
<DialogContent
|
|
14
|
-
class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-modal text-left align-middle shadow-xl dialog-content"
|
|
14
|
+
class="my-8 inline-block w-full transform overflow-hidden rounded-xl bg-surface-modal text-left align-middle shadow-xl dialog-content focus-visible:outline-none"
|
|
15
15
|
:class="{
|
|
16
16
|
'max-w-7xl': options.size === '7xl',
|
|
17
17
|
'max-w-6xl': options.size === '6xl',
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
class="flex h-full w-full flex-col items-center justify-center text-base"
|
|
4
4
|
>
|
|
5
5
|
<slot>
|
|
6
|
-
<div class="text-xl font-medium">{{ list.options.emptyState.title }}</div>
|
|
6
|
+
<div class="text-xl font-medium text-ink-gray-8 mt-6">{{ list.options.emptyState.title }}</div>
|
|
7
7
|
<div class="mt-1 text-base text-ink-gray-5">
|
|
8
8
|
{{ list.options.emptyState.description }}
|
|
9
9
|
</div>
|
|
@@ -204,7 +204,9 @@ function setCursorBeforeIframe() {
|
|
|
204
204
|
v-if="node.attrs.src"
|
|
205
205
|
ref="iframeRef"
|
|
206
206
|
class="rounded-lg border-0 block max-w-full h-auto"
|
|
207
|
-
:class="{
|
|
207
|
+
:class="{
|
|
208
|
+
'pointer-events-none': isEditable && !props.node.attrs.interactive,
|
|
209
|
+
}"
|
|
208
210
|
:src="node.attrs.src"
|
|
209
211
|
:style="iframeStyles"
|
|
210
212
|
:title="node.attrs.title || ''"
|
|
@@ -218,7 +220,7 @@ function setCursorBeforeIframe() {
|
|
|
218
220
|
|
|
219
221
|
<!-- Transparent overlay for selection in edit mode -->
|
|
220
222
|
<div
|
|
221
|
-
v-if="isEditable"
|
|
223
|
+
v-if="isEditable && !props.node.attrs.interactive"
|
|
222
224
|
class="absolute inset-0 cursor-pointer z-10"
|
|
223
225
|
@click.stop="selectIframe"
|
|
224
226
|
></div>
|
|
@@ -20,6 +20,7 @@ export interface SetIframeOptions {
|
|
|
20
20
|
width?: number
|
|
21
21
|
height?: number
|
|
22
22
|
title?: string
|
|
23
|
+
interactive?: boolean
|
|
23
24
|
align?: 'left' | 'center' | 'right'
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -128,6 +129,13 @@ export const IframeExtension = Node.create<IframeOptions>({
|
|
|
128
129
|
sandbox: attributes.sandbox,
|
|
129
130
|
}),
|
|
130
131
|
},
|
|
132
|
+
interactive: {
|
|
133
|
+
default: false,
|
|
134
|
+
parseHTML: (el) => el.getAttribute('data-interactive') === 'true',
|
|
135
|
+
renderHTML: (attrs) => ({
|
|
136
|
+
'data-interactive': attrs.interactive ? 'true' : 'false',
|
|
137
|
+
}),
|
|
138
|
+
},
|
|
131
139
|
}
|
|
132
140
|
},
|
|
133
141
|
|
|
@@ -196,7 +204,8 @@ export const IframeExtension = Node.create<IframeOptions>({
|
|
|
196
204
|
height: options.height || optimalDimensions.height,
|
|
197
205
|
title: options.title,
|
|
198
206
|
align: options.align || 'center',
|
|
199
|
-
aspectRatio: optimalDimensions.height / optimalDimensions.width
|
|
207
|
+
aspectRatio: optimalDimensions.height / optimalDimensions.width,
|
|
208
|
+
interactive: options.interactive,
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
return commands.insertContent({
|
|
@@ -133,6 +133,7 @@ export function getOptimalDimensions(url: string, containerWidth?: number): { wi
|
|
|
133
133
|
|
|
134
134
|
export function validateURL(url: string, options: IframeOptions): boolean {
|
|
135
135
|
try {
|
|
136
|
+
if (url.startsWith('/')) return true
|
|
136
137
|
const urlObj = new URL(url)
|
|
137
138
|
const domain = urlObj.hostname.toLowerCase()
|
|
138
139
|
|
|
@@ -40,6 +40,9 @@ export function createDocumentResource(options, vm) {
|
|
|
40
40
|
fieldname: values,
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
|
+
validate(data) {
|
|
44
|
+
options.setValue?.validate?.call(vm, data)
|
|
45
|
+
},
|
|
43
46
|
beforeSubmit(params) {
|
|
44
47
|
out.previousDoc = JSON.stringify(out.doc)
|
|
45
48
|
Object.assign(out.doc, params.fieldname || {})
|
package/vite/melonProxy.js
CHANGED
|
@@ -5,7 +5,7 @@ export function melonProxy({
|
|
|
5
5
|
source = '^/(app|login|api|assets|files|private)',
|
|
6
6
|
} = {}) {
|
|
7
7
|
const commonSiteConfig = getCommonSiteConfig()
|
|
8
|
-
const env_web_server_port = process.env.
|
|
8
|
+
const env_web_server_port = process.env.MELON_WEB_SERVER_PORT
|
|
9
9
|
const webserver_port =
|
|
10
10
|
env_web_server_port ||
|
|
11
11
|
(commonSiteConfig ? commonSiteConfig.webserver_port : 8000)
|