Add datetime input

This commit is contained in:
Jon Staab
2024-09-12 16:56:33 -07:00
parent 6d9325dab4
commit 0d53934152
9 changed files with 156 additions and 69 deletions
+50 -21
View File
@@ -23,13 +23,14 @@
"@tiptap/extension-text": "^2.6.6",
"@tiptap/suggestion": "^2.6.4",
"@types/throttle-debounce": "^5.0.2",
"@welshman/app": "^0.0.4",
"@welshman/app": "^0.0.5",
"@welshman/lib": "^0.0.17",
"@welshman/net": "^0.0.21",
"@welshman/net": "^0.0.22",
"@welshman/signer": "^0.0.5",
"@welshman/store": "^0.0.5",
"@welshman/util": "^0.0.30",
"@welshman/store": "^0.0.6",
"@welshman/util": "^0.0.31",
"daisyui": "^4.12.10",
"date-picker-svelte": "^2.13.0",
"fuse.js": "^7.0.0",
"idb": "^8.0.0",
"nostr-editor": "^0.0.1",
@@ -1654,15 +1655,15 @@
}
},
"node_modules/@welshman/app": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/@welshman/app/-/app-0.0.4.tgz",
"integrity": "sha512-Xouy66xz1tnMjlDAlxtKF+1lHVJyM2sRiC6RONDmt75HXUnuvMX19sssRy4AFwb8jychBr8EMjYanVX2EV1Sow==",
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@welshman/app/-/app-0.0.5.tgz",
"integrity": "sha512-T7iXybwBnFN9E1GWeGQ6ZxvFrQ3EUUWHsZdG3Q+s57YxBDqDkRy+eOtxaDb2EBmgyflheERaggOlzFFTsmUjyA==",
"dependencies": {
"@welshman/lib": "0.0.17",
"@welshman/net": "0.0.21",
"@welshman/net": "0.0.22",
"@welshman/signer": "0.0.5",
"@welshman/store": "0.0.5",
"@welshman/util": "0.0.30",
"@welshman/store": "0.0.6",
"@welshman/util": "0.0.31",
"fuse.js": "^7.0.0",
"idb": "^8.0.0",
"svelte": "^4.2.18",
@@ -1682,12 +1683,12 @@
}
},
"node_modules/@welshman/net": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@welshman/net/-/net-0.0.21.tgz",
"integrity": "sha512-BOWRevNJjyNHshxr0eFn/yBjjVIuvofyy/Q+eYuLLTRwolFkqmaiN8xuG3wFndPi5z2uuC87Ay4PmRTzp+kCSg==",
"version": "0.0.22",
"resolved": "https://registry.npmjs.org/@welshman/net/-/net-0.0.22.tgz",
"integrity": "sha512-sXdHevglDqLujQrhXFUwSPsC0Zu/SY2WWy049Citpi1nej4JnAjCbpI8XUeI1it80a84dWa+vGA5Da4OhCYkmA==",
"dependencies": {
"@welshman/lib": "0.0.17",
"@welshman/util": "0.0.30",
"@welshman/util": "0.0.31",
"isomorphic-ws": "^5.0.0",
"ws": "^8.16.0"
}
@@ -1703,20 +1704,40 @@
"nostr-tools": "^2.7.2"
}
},
"node_modules/@welshman/store": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@welshman/store/-/store-0.0.5.tgz",
"integrity": "sha512-AH8TsaZ63s4ln4NBO2/DjtmBFPZlxXnDiyV3wScj6Ts0vahZCinlrL8pAIfLzvZ2QvjcnFiPf081kghhr3Baaw==",
"node_modules/@welshman/signer/node_modules/@welshman/net": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@welshman/net/-/net-0.0.21.tgz",
"integrity": "sha512-BOWRevNJjyNHshxr0eFn/yBjjVIuvofyy/Q+eYuLLTRwolFkqmaiN8xuG3wFndPi5z2uuC87Ay4PmRTzp+kCSg==",
"dependencies": {
"@welshman/lib": "0.0.17",
"@welshman/util": "0.0.30",
"isomorphic-ws": "^5.0.0",
"ws": "^8.16.0"
}
},
"node_modules/@welshman/signer/node_modules/@welshman/util": {
"version": "0.0.30",
"resolved": "https://registry.npmjs.org/@welshman/util/-/util-0.0.30.tgz",
"integrity": "sha512-CYLtaXfCod5Xo/OCXPUGYKwT+fRwm5DU7ASqcGwPuB/vadDodT/OJPSmrMH9Pq63VY9xK4gX/I2ma/rKRokdpg==",
"dependencies": {
"@welshman/lib": "0.0.17",
"nostr-tools": "^2.7.2"
}
},
"node_modules/@welshman/store": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@welshman/store/-/store-0.0.6.tgz",
"integrity": "sha512-yZDnXcIZ2fcqvK+1W9OTRXJy3IPKE3ykFp5VnUT5bGMSRSTIyHnPO5swsgDLofe5Zswdee0lJTwE5IQBthf0pQ==",
"dependencies": {
"@welshman/lib": "0.0.17",
"@welshman/util": "0.0.31",
"svelte": "^4.2.18"
}
},
"node_modules/@welshman/util": {
"version": "0.0.30",
"resolved": "https://registry.npmjs.org/@welshman/util/-/util-0.0.30.tgz",
"integrity": "sha512-CYLtaXfCod5Xo/OCXPUGYKwT+fRwm5DU7ASqcGwPuB/vadDodT/OJPSmrMH9Pq63VY9xK4gX/I2ma/rKRokdpg==",
"version": "0.0.31",
"resolved": "https://registry.npmjs.org/@welshman/util/-/util-0.0.31.tgz",
"integrity": "sha512-nUv/Mto6maQx6vbCaZ0HKQRvLYRWqQzPTLsKoxSDX0HkeFP653T6raFx8TvWt+op/qBuuT8sANJactc2/qGoYg==",
"dependencies": {
"@welshman/lib": "0.0.17",
"nostr-tools": "^2.7.2"
@@ -2316,6 +2337,14 @@
"node": ">=18"
}
},
"node_modules/date-picker-svelte": {
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/date-picker-svelte/-/date-picker-svelte-2.13.0.tgz",
"integrity": "sha512-A0MMma1uv+/sL8MwgGuEPv/UJnhR6CmWg5aR8XhYeAX/I8+RQmQh+jpwIL0Z3/g4CGo9OhNZn+VicHpvnNCCtA==",
"peerDependencies": {
"svelte": "^3.24.0 || ^4.0.0"
}
},
"node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
+1
View File
@@ -55,6 +55,7 @@
"@welshman/store": "^0.0.6",
"@welshman/util": "^0.0.31",
"daisyui": "^4.12.10",
"date-picker-svelte": "^2.13.0",
"fuse.js": "^7.0.0",
"idb": "^8.0.0",
"nostr-editor": "^0.0.1",
+23 -1
View File
@@ -92,8 +92,21 @@
/* tiptap */
.input-editor, .chat-editor {
@apply p-1 -m-1 min-h-12;
}
.tiptap[contenteditable="true"] {
@apply max-h-[350px] overflow-y-auto rounded-box bg-base-300 p-2 px-4;
@apply max-h-[350px] overflow-y-auto p-2 px-4;
}
.chat-editor .tiptap[contenteditable="true"] {
@apply rounded-box bg-base-300;
}
.input-editor .tiptap[contenteditable="true"] {
@apply input input-bordered p-[.65rem] h-auto;
}
.tiptap pre code {
@@ -111,3 +124,12 @@
.link-content.link-content-selected {
@apply bg-primary text-primary-content;
}
/* date input */
.date-time-field {
@apply input input-bordered px-0 rounded;
}
.date-time-field input {
@apply !bg-inherit !border-none !text-inherit !w-full !h-full;
}
+1 -1
View File
@@ -57,7 +57,7 @@
<Icon icon="gallery-send" />
{/if}
</Button>
<div class="flex-grow overflow-hidden">
<div class="flex-grow overflow-hidden chat-editor">
<EditorContent editor={$editor} />
</div>
</div>
+33 -5
View File
@@ -10,9 +10,11 @@
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import {makeMention, makeIMeta} from "@app/commands"
import {getNoteEditorOptions, addFile} from "@app/editor"
import {pushModal} from "@app/modal"
import {pushToast} from "@app/toast"
export let url
@@ -23,6 +25,20 @@
const uploading = writable(false)
const sendMessage = () => {
if (!title) {
return pushToast({
theme: "error",
message: "Please provide a title.",
})
}
if (!start || !end) {
return pushToast({
theme: "error",
message: "Please provide start and end times.",
})
}
const json = $editor.getJSON()
const kind = isAllDay ? EVENT_DATE : EVENT_TIME
const mentionTags = findNodes(NProfileExtension.name, json).map(m =>
@@ -47,8 +63,8 @@
let file: File
let title = ""
let location = ""
let start = ""
let end = ""
let start: Date
let end: Date
onMount(() => {
editor = createEditor(getNoteEditorOptions({uploading, sendMessage}))
@@ -71,9 +87,12 @@
<div
slot="input"
class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100">
<div class="flex-grow overflow-hidden input-editor">
<EditorContent editor={$editor} />
</div>
<Button
data-tip="Add an image"
class="center h-10 w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200 tooltip"
class="btn center tooltip"
on:click={() => addFile($editor)}>
{#if $uploading}
<span class="loading loading-spinner loading-xs"></span>
@@ -81,8 +100,17 @@
<Icon icon="gallery-send" />
{/if}
</Button>
<div class="flex-grow overflow-hidden">
<EditorContent editor={$editor} />
</div>
</Field>
<Field>
<div slot="input" class="grid grid-cols-2 gap-2">
<div class="flex flex-col gap-1">
<strong>Start</strong>
<DateTimeInput bind:value={start} />
</div>
<div class="flex flex-col gap-1">
<strong>End</strong>
<DateTimeInput bind:value={end} />
</div>
</div>
</Field>
-1
View File
@@ -149,7 +149,6 @@ export const getChatViewOptions = (content: string) => ({
export const getNoteEditorOptions = ({uploading, sendMessage}: EditorOptions) => ({
content: "",
autofocus: true,
extensions: [
Document,
Dropcursor,
+36
View File
@@ -0,0 +1,36 @@
<script lang="ts">
import cx from 'classnames'
import {DateInput} from "date-picker-svelte"
import {formatTimestamp} from '@welshman/app'
import Icon from '@lib/components/Icon.svelte'
import Button from '@lib/components/Button.svelte'
export let initialValue: Date | undefined = undefined
export let value: Date | undefined = initialValue
const init = () => {
if (!value) {
value = new Date()
value.setMinutes(0, 0, 0)
}
}
const clear = () => {
value = undefined
}
</script>
<label class="relative">
<DateInput format="yyyy-MM-dd HH:mm" placeholder="" bind:value />
<div class="absolute top-0 h-12 right-2 flex gap-2 items-center cursor-pointer">
{#if value}
<Button on:click={clear} class="h-5">
<Icon icon="close-circle" />
</Button>
{:else}
<Button on:click={init} class="h-5">
<Icon icon="calendar-minimalistic" />
</Button>
{/if}
</div>
</label>
+3 -31
View File
@@ -1,38 +1,10 @@
<script context="module" lang="ts">
import {emitter} from "@app/modal"
const modalHeight = tweened(0, {
duration: 700,
easing: quintOut,
})
emitter.on("close", () => modalHeight.set(0))
</script>
<script lang="ts">
import {onMount} from "svelte"
import {quintOut} from "svelte/easing"
import {tweened} from "svelte/motion"
import {fly} from "@lib/transition"
export let component
export let props = {}
let box: HTMLElement
let content: HTMLElement
let naturalHeight = 0
onMount(() => {
naturalHeight = content.clientHeight + 48
modalHeight.set(naturalHeight)
})
</script>
<div
class="modal-box"
bind:this={box}
style={`height: ${$modalHeight}px`}
class:overflow-hidden={$modalHeight !== naturalHeight}>
<div bind:this={content}>
<svelte:component this={component} {...props} />
</div>
<div class="modal-box" transition:fly={{duration: 100}}>
<svelte:component this={component} {...props} />
</div>
+9 -9
View File
@@ -70,7 +70,7 @@
{#if showMenu}
<Popover hideOnClick onClose={toggleMenu}>
<ul
transition:fly|local
transition:fly
class="menu absolute z-popover mt-2 w-full rounded-box bg-base-100 p-2 shadow-xl">
{#if $userMembership?.topicsByUrl.has(url)}
<li class="text-error">
@@ -92,29 +92,29 @@
{/if}
</div>
<div class="my-3 h-px bg-base-200" />
<div in:fly|local>
<div in:fly>
<SecondaryNavItem href={makeSpacePath(url)}>
<Icon icon="chat-round" /> Chat
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: getDelay(true)}}>
<div in:fly={{delay: getDelay(true)}}>
<SecondaryNavItem href={makeSpacePath(url, "threads")}>
<Icon icon="notes-minimalistic" /> Threads
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: getDelay()}}>
<div in:fly={{delay: getDelay()}}>
<SecondaryNavItem href={makeSpacePath(url, "calendar")}>
<Icon icon="calendar-minimalistic" /> Calendar
</SecondaryNavItem>
</div>
{#if rooms.length > 0}
<div transition:slide|local={{delay: getDelay()}}>
<div transition:slide={{delay: getDelay()}}>
<div class="h-2" />
<SecondaryNavHeader>Your Rooms</SecondaryNavHeader>
</div>
{/if}
{#each rooms as topic, i (topic)}
<div transition:slide|local={{delay: getDelay()}}>
<div transition:slide={{delay: getDelay()}}>
<SecondaryNavItem href={makeSpacePath(url, topic)}>
<Icon icon="hashtag" />
{topic}
@@ -122,7 +122,7 @@
</div>
{/each}
{#if otherRooms.length > 0}
<div transition:slide|local={{delay: getDelay()}}>
<div transition:slide={{delay: getDelay()}}>
<div class="h-2" />
<SecondaryNavHeader>
{#if rooms.length > 0}
@@ -134,14 +134,14 @@
</div>
{/if}
{#each otherRooms as topic, i (topic)}
<div transition:slide|local={{delay: getDelay()}}>
<div transition:slide={{delay: getDelay()}}>
<SecondaryNavItem href={makeSpacePath(url, topic)}>
<Icon icon="hashtag" />
{topic}
</SecondaryNavItem>
</div>
{/each}
<div in:fly|local={{delay: getDelay()}}>
<div in:fly={{delay: getDelay()}}>
<SecondaryNavItem on:click={addRoom}>
<Icon icon="add-circle" />
Create room