mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 09:22:41 +03:00
Cleanup @/util
folder (#8501)
- Partially addresses #8228 - Moves several files into `@/util/vue` and `@/util/data` - Makes imports more consistent: - Remove redundant trailing `.ts` - Convert *some* imports to use `@/` rather than `./` - Ideally it should be all imports other than the ones outside of `src/`, but I can't be sure I've found all of them - Merge *some* duplicated imports (caused by one being an `import type`) # Important Notes None
This commit is contained in:
parent
f5c3713f87
commit
9fb3d9a2fa
@ -4,8 +4,8 @@ import { createApp, ref } from 'vue'
|
||||
import '../src/assets/base.css'
|
||||
import { provideGuiConfig } from '../src/providers/guiConfig'
|
||||
import { provideVisualizationConfig } from '../src/providers/visualizationConfig'
|
||||
import { Vec2 } from '../src/util/data/vec2'
|
||||
import { MockTransport, MockWebSocket } from '../src/util/net'
|
||||
import { Vec2 } from '../src/util/vec2'
|
||||
import MockApp from './MockApp.vue'
|
||||
import { mockDataHandler, mockLSHandler } from './mockEngine'
|
||||
|
||||
|
@ -13,8 +13,18 @@ await fs.writeFile(
|
||||
`\
|
||||
// Generated by \`scripts/generateIcons.js\`.
|
||||
// Please run \`npm run generate\` to regenerate this file whenever \`icons.svg\` is changed.
|
||||
import iconNames from '@/util/iconList.json'
|
||||
|
||||
export type Icon =
|
||||
${iconNames?.map((name) => ` | '${name}'`).join('\n')}
|
||||
|
||||
export { iconNames }
|
||||
|
||||
const iconNamesSet = new Set(iconNames)
|
||||
|
||||
export function isIconName(value: string): value is Icon {
|
||||
return iconNamesSet.has(value)
|
||||
}
|
||||
`,
|
||||
)
|
||||
console.info('Done.')
|
||||
|
@ -1,16 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { Diagnostic, Highlighter } from '@/components/CodeEditor/codemirror'
|
||||
import { usePointer } from '@/composables/events'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { useSuggestionDbStore } from '@/stores/suggestionDatabase'
|
||||
import { useAutoBlur } from '@/util/autoBlur'
|
||||
import type { Diagnostic, Highlighter } from '@/util/codemirror'
|
||||
import { usePointer } from '@/util/events'
|
||||
import { chain } from '@/util/iterable'
|
||||
import { chain } from '@/util/data/iterable'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import { qnJoin, tryQualifiedName } from '@/util/qualifiedName'
|
||||
import { useLocalStorage } from '@vueuse/core'
|
||||
import { rangeEncloses, type ExprId } from 'shared/yjsModel'
|
||||
import { computed, onMounted, ref, watch, watchEffect } from 'vue'
|
||||
import { qnJoin, tryQualifiedName } from '../util/qualifiedName'
|
||||
import { unwrap } from '../util/result'
|
||||
|
||||
// Use dynamic imports to aid code splitting. The codemirror dependency is quite large.
|
||||
const {
|
||||
@ -30,7 +30,7 @@ const {
|
||||
forceLinting,
|
||||
lsDiagnosticsToCMDiagnostics,
|
||||
hoverTooltip,
|
||||
} = await import('@/util/codemirror')
|
||||
} = await import('@/components/CodeEditor/codemirror')
|
||||
|
||||
const projectStore = useProjectStore()
|
||||
const graphStore = useGraphStore()
|
||||
|
@ -2,26 +2,26 @@
|
||||
import { componentBrowserBindings } from '@/bindings'
|
||||
import { makeComponentList, type Component } from '@/components/ComponentBrowser/component'
|
||||
import { Filtering } from '@/components/ComponentBrowser/filtering'
|
||||
import { useComponentBrowserInput, type Usage } from '@/components/ComponentBrowser/input'
|
||||
import { default as DocumentationPanel } from '@/components/DocumentationPanel.vue'
|
||||
import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue'
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import ToggleIcon from '@/components/ToggleIcon.vue'
|
||||
import { useApproach } from '@/composables/animation'
|
||||
import { useEvent, useResizeObserver } from '@/composables/events'
|
||||
import type { useNavigator } from '@/composables/navigator'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import type { RequiredImport } from '@/stores/graph/imports'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { groupColorStyle, useSuggestionDbStore } from '@/stores/suggestionDatabase'
|
||||
import { SuggestionKind, type SuggestionEntry } from '@/stores/suggestionDatabase/entry'
|
||||
import type { VisualizationDataSource } from '@/stores/visualization'
|
||||
import { useApproach } from '@/util/animation'
|
||||
import { tryGetIndex } from '@/util/array'
|
||||
import { useEvent, useResizeObserver } from '@/util/events'
|
||||
import type { useNavigator } from '@/util/navigator'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { allRanges } from '@/util/range'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { tryGetIndex } from '@/util/data/array'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { allRanges } from '@/util/data/range'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import type { SuggestionId } from 'shared/languageServerTypes/suggestions'
|
||||
import { computed, nextTick, onMounted, ref, watch, type ComputedRef, type Ref } from 'vue'
|
||||
import { useComponentBrowserInput, type Usage } from './ComponentBrowser/input'
|
||||
import GraphVisualization from './GraphEditor/GraphVisualization.vue'
|
||||
|
||||
const ITEM_SIZE = 32
|
||||
const TOP_BAR_HEIGHT = 32
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
makeStaticMethod,
|
||||
type SuggestionEntry,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { allRanges } from '@/util/range'
|
||||
import { allRanges } from '@/util/data/range'
|
||||
import shuffleSeed from 'shuffle-seed'
|
||||
|
||||
test.each([
|
||||
|
@ -11,8 +11,8 @@ import {
|
||||
makeStaticMethod,
|
||||
makeType,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import { tryQualifiedName, type QualifiedName } from '@/util/qualifiedName'
|
||||
import { unwrap } from '@/util/result'
|
||||
|
||||
test.each([
|
||||
{ ...makeModuleMethod('Standard.Base.Data.read'), groupIndex: 0 },
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useComponentBrowserInput } from '@/components/ComponentBrowser/input'
|
||||
import { GraphDb } from '@/stores/graph/graphDatabase'
|
||||
import type { RequiredImport } from '@/stores/graph/imports'
|
||||
import { ComputedValueRegistry } from '@/stores/project/computedValueRegistry'
|
||||
@ -13,11 +14,10 @@ import {
|
||||
makeType,
|
||||
type SuggestionEntry,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import { tryIdentifier, tryQualifiedName } from '@/util/qualifiedName'
|
||||
import { unwrap } from '@/util/result'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import { expect, test } from 'vitest'
|
||||
import { useComponentBrowserInput } from '../input'
|
||||
|
||||
test.each([
|
||||
['', 0, { type: 'insert', position: 0 }, {}],
|
||||
|
@ -5,10 +5,10 @@ import {
|
||||
type Environment,
|
||||
type Placement,
|
||||
} from '@/components/ComponentBrowser/placement'
|
||||
import * as iterable from '@/util/iterable'
|
||||
import { chain, map, range } from '@/util/iterable'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import * as iterable from '@/util/data/iterable'
|
||||
import { chain, map, range } from '@/util/data/iterable'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { fc, test as fcTest } from '@fast-check/vitest'
|
||||
import { describe, expect, test, vi } from 'vitest'
|
||||
|
||||
|
@ -6,11 +6,11 @@ import {
|
||||
type SuggestionId,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { compareOpt } from '@/util/compare'
|
||||
import { isSome } from '@/util/data/opt'
|
||||
import { Range } from '@/util/data/range'
|
||||
import { displayedIconOf } from '@/util/getIconName'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import { isSome } from '@/util/opt'
|
||||
import { qnIsTopElement, qnLastSegmentIndex } from '@/util/qualifiedName'
|
||||
import { Range } from '@/util/range'
|
||||
|
||||
interface ComponentLabel {
|
||||
label: string
|
||||
|
@ -3,9 +3,9 @@ import {
|
||||
type SuggestionEntry,
|
||||
type Typename,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Range } from '@/util/data/range'
|
||||
import { qnIsTopElement, qnParent, type QualifiedName } from '@/util/qualifiedName'
|
||||
import { Range } from '@/util/range'
|
||||
|
||||
export type SelfArg =
|
||||
| {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { bail } from '@/util/assert'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import theme from '@/util/theme.json'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
|
||||
export interface Environment {
|
||||
screenBounds: Rect
|
||||
|
@ -11,9 +11,9 @@ import type { Docs, FunctionDocs, Sections, TypeDocs } from '@/components/Docume
|
||||
import { lookupDocumentation, placeholder } from '@/components/DocumentationPanel/ir'
|
||||
import { groupColorStyle, useSuggestionDbStore } from '@/stores/suggestionDatabase'
|
||||
import type { SuggestionId } from '@/stores/suggestionDatabase/entry'
|
||||
import { tryGetIndex } from '@/util/array'
|
||||
import { tryGetIndex } from '@/util/data/array'
|
||||
import { type Opt } from '@/util/data/opt'
|
||||
import type { Icon as IconName } from '@/util/iconName'
|
||||
import { type Opt } from '@/util/opt'
|
||||
import type { QualifiedName } from '@/util/qualifiedName'
|
||||
import { qnSegments, qnSlice } from '@/util/qualifiedName'
|
||||
import { computed, watch } from 'vue'
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useEvent } from '@/util/events'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps<{ modes: string[]; modelValue: string }>()
|
||||
|
@ -7,14 +7,15 @@ import {
|
||||
nonDictatedPlacement,
|
||||
previousNodeDictatedPlacement,
|
||||
type Environment,
|
||||
} from '@/components/ComponentBrowser/placement.ts'
|
||||
} from '@/components/ComponentBrowser/placement'
|
||||
import GraphEdges from '@/components/GraphEditor/GraphEdges.vue'
|
||||
import GraphNodes from '@/components/GraphEditor/GraphNodes.vue'
|
||||
import { Uploader, uploadedExpression } from '@/components/GraphEditor/upload'
|
||||
import GraphMouse from '@/components/GraphMouse.vue'
|
||||
import PlusButton from '@/components/PlusButton.vue'
|
||||
import TopBar from '@/components/TopBar.vue'
|
||||
import { useDoubleClick } from '@/composables/doubleClick.ts'
|
||||
import { useDoubleClick } from '@/composables/doubleClick'
|
||||
import { keyboardBusy, keyboardBusyExceptIn, useEvent } from '@/composables/events'
|
||||
import { provideGraphNavigator } from '@/providers/graphNavigator'
|
||||
import { provideGraphSelection } from '@/providers/graphSelection'
|
||||
import { provideInteractionHandler, type Interaction } from '@/providers/interactionHandler'
|
||||
@ -24,12 +25,11 @@ import type { RequiredImport } from '@/stores/graph/imports'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { groupColorVar, useSuggestionDbStore } from '@/stores/suggestionDatabase'
|
||||
import { colorFromString } from '@/util/colors'
|
||||
import { keyboardBusy, keyboardBusyExceptIn, useEvent } from '@/util/events'
|
||||
import { qnLastSegment, tryQualifiedName } from '@/util/qualifiedName.ts'
|
||||
import { Rect } from '@/util/rect.ts'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { qnLastSegment, tryQualifiedName } from '@/util/qualifiedName'
|
||||
import * as set from 'lib0/set'
|
||||
import type { ExprId, NodeMetadata } from 'shared/yjsModel.ts'
|
||||
import type { ExprId, NodeMetadata } from 'shared/yjsModel'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { type Usage } from './ComponentBrowser/input'
|
||||
|
||||
@ -216,7 +216,7 @@ const graphBindingsHandler = graphBindings.handler({
|
||||
})
|
||||
|
||||
const handleClick = useDoubleClick(
|
||||
(e) => {
|
||||
(e: MouseEvent) => {
|
||||
graphBindingsHandler(e)
|
||||
},
|
||||
() => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { injectGraphNavigator } from '@/providers/graphNavigator.ts'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection.ts'
|
||||
import { injectGraphNavigator } from '@/providers/graphNavigator'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { useGraphStore, type Edge } from '@/stores/graph'
|
||||
import { assert } from '@/util/assert'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import theme from '@/util/theme.json'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { clamp } from '@vueuse/core'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import GraphEdge from '@/components/GraphEditor/GraphEdge.vue'
|
||||
import type { GraphNavigator } from '@/providers/graphNavigator.ts'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection.ts'
|
||||
import type { GraphNavigator } from '@/providers/graphNavigator'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { injectInteractionHandler, type Interaction } from '@/providers/interactionHandler'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { Vec2 } from '@/util/vec2.ts'
|
||||
import type { ExprId } from 'shared/yjsModel.ts'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
|
||||
const graph = useGraphStore()
|
||||
const selection = injectGraphSelection(true)
|
||||
|
@ -5,17 +5,17 @@ import GraphNodeError from '@/components/GraphEditor/GraphNodeError.vue'
|
||||
import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue'
|
||||
import NodeWidgetTree from '@/components/GraphEditor/NodeWidgetTree.vue'
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useApproach } from '@/composables/animation'
|
||||
import { useDoubleClick } from '@/composables/doubleClick'
|
||||
import { usePointer, useResizeObserver } from '@/composables/events'
|
||||
import { injectGraphNavigator } from '@/providers/graphNavigator'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { useGraphStore, type Node } from '@/stores/graph'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { useApproach } from '@/util/animation'
|
||||
import { usePointer, useResizeObserver } from '@/util/events'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { displayedIconOf } from '@/util/getIconName'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { setIfUndefined } from 'lib0/map'
|
||||
import type { ContentRange, ExprId, VisualizationIdentifier } from 'shared/yjsModel'
|
||||
import { computed, ref, watch, watchEffect } from 'vue'
|
||||
@ -214,20 +214,14 @@ function getRelatedSpanOffset(domNode: globalThis.Node, domOffset: number): numb
|
||||
return domOffset
|
||||
}
|
||||
|
||||
const handlePortClick = useDoubleClick<[portId: ExprId]>(
|
||||
(_e, portId) => emit('outputPortClick', portId),
|
||||
(portId) => {
|
||||
emit('outputPortDoubleClick', portId)
|
||||
},
|
||||
const handlePortClick = useDoubleClick(
|
||||
(portId: ExprId) => emit('outputPortClick', portId),
|
||||
(portId: ExprId) => emit('outputPortDoubleClick', portId),
|
||||
).handleClick
|
||||
|
||||
const handleNodeClick = useDoubleClick(
|
||||
(e) => {
|
||||
nodeEditHandler(e)
|
||||
},
|
||||
() => {
|
||||
emit('doubleClick')
|
||||
},
|
||||
(e: MouseEvent) => nodeEditHandler(e),
|
||||
() => emit('doubleClick'),
|
||||
).handleClick
|
||||
interface PortData {
|
||||
clipRange: [number, number]
|
||||
@ -339,7 +333,7 @@ function portGroupStyle(port: PortData) {
|
||||
class="outputPortHoverArea"
|
||||
@pointerenter="outputHovered = port.portId"
|
||||
@pointerleave="outputHovered = undefined"
|
||||
@pointerdown.stop.prevent="handlePortClick($event, port.portId)"
|
||||
@pointerdown.stop.prevent="handlePortClick(port.portId)"
|
||||
/>
|
||||
<rect class="outputPort" />
|
||||
</g>
|
||||
|
@ -7,7 +7,7 @@ import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import type { UploadingFile as File, FileName } from '@/stores/awareness'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import type { Vec2 } from '@/util/vec2'
|
||||
import type { Vec2 } from '@/util/data/vec2'
|
||||
import { stackItemsEqual } from 'shared/languageServerTypes'
|
||||
import type { ContentRange, ExprId } from 'shared/yjsModel'
|
||||
import { computed, toRaw } from 'vue'
|
||||
|
@ -11,13 +11,13 @@ import {
|
||||
type VisualizationDataSource,
|
||||
} from '@/stores/visualization'
|
||||
import type { Visualization } from '@/stores/visualization/runtimeTypes'
|
||||
import { toError } from '@/util/error'
|
||||
import { toError } from '@/util/data/error'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import type { Result } from '@/util/data/result'
|
||||
import type { URLString } from '@/util/data/urlString'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Rect } from '@/util/rect'
|
||||
import type { Result } from '@/util/result'
|
||||
import type { URLString } from '@/util/urlString'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import type { VisualizationIdentifier } from 'shared/yjsModel'
|
||||
import {
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
usageKeyForInput,
|
||||
} from '@/providers/widgetUsageInfo'
|
||||
import { Ast } from '@/util/ast'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { computed, proxyRefs } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
|
||||
import { useTransitioning } from '@/composables/animation'
|
||||
import { ForcePort } from '@/providers/portInfo'
|
||||
import { provideWidgetTree } from '@/providers/widgetTree'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { useTransitioning } from '@/util/animation'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { computed, toRef } from 'vue'
|
||||
import NodeWidget from './NodeWidget.vue'
|
||||
|
||||
const props = defineProps<{ ast: Ast.Ast }>()
|
||||
const graph = useGraphStore()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SnapGrid } from '@/components/GraphEditor/dragging'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { expect, test } from 'vitest'
|
||||
import { computed } from 'vue'
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { useApproach } from '@/composables/animation'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { useApproach } from '@/util/animation'
|
||||
import { partitionPoint } from '@/util/array'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { partitionPoint } from '@/util/data/array'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import theme from '@/util/theme.json'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { iteratorFilter } from 'lib0/iterator'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import { computed, markRaw, ref, watchEffect, type ComputedRef, type WatchStopHandle } from 'vue'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Awareness } from '@/stores/awareness'
|
||||
import * as astText from '@/util/ast/text'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { Keccak, sha3_224 as SHA3 } from '@noble/hashes/sha3'
|
||||
import type { Hash } from '@noble/hashes/utils'
|
||||
import { bytesToHex } from '@noble/hashes/utils'
|
||||
|
@ -7,7 +7,7 @@ import { useGraphStore } from '@/stores/graph'
|
||||
import { useProjectStore, type NodeVisualizationConfiguration } from '@/stores/project'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { ArgumentApplication } from '@/util/callTree'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import { computed, proxyRefs } from 'vue'
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
|
||||
import { useRaf } from '@/composables/animation'
|
||||
import { useResizeObserver } from '@/composables/events'
|
||||
import { injectGraphNavigator } from '@/providers/graphNavigator'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { ForcePort, injectPortInfo, providePortInfo } from '@/providers/portInfo'
|
||||
@ -7,11 +9,9 @@ import type { WidgetInput } from '@/providers/widgetRegistry'
|
||||
import { Score, defineWidget, widgetProps } from '@/providers/widgetRegistry'
|
||||
import { injectWidgetTree } from '@/providers/widgetTree'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { useRaf } from '@/util/animation'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { ArgumentAst, ArgumentPlaceholder } from '@/util/callTree'
|
||||
import { useResizeObserver } from '@/util/events'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { uuidv4 } from 'lib0/random'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import {
|
||||
|
@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
|
||||
import DropdownWidget from '@/components/widgets/DropdownWidget.vue'
|
||||
import { widgetProps } from '@/providers/widgetRegistry'
|
||||
import { Score, defineWidget, widgetProps } from '@/providers/widgetRegistry'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import { qnJoin, qnSegments, tryQualifiedName } from '@/util/qualifiedName.ts'
|
||||
import { ArgumentAst, ArgumentPlaceholder } from '@/util/callTree'
|
||||
import { qnJoin, qnSegments, tryQualifiedName } from '@/util/qualifiedName'
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps(widgetProps(widgetDefinition))
|
||||
@ -89,9 +90,6 @@ watch(selectedIndex, (_index) => {
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineWidget, Score } from '@/providers/widgetRegistry.ts'
|
||||
import { ArgumentAst, ArgumentPlaceholder } from '@/util/callTree.ts'
|
||||
|
||||
export const widgetDefinition = defineWidget([ArgumentPlaceholder, ArgumentAst], {
|
||||
priority: 999,
|
||||
score: (props) => {
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import SelectionBrush from '@/components/SelectionBrush.vue'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import { injectGraphNavigator } from '@/providers/graphNavigator'
|
||||
import { injectGraphSelection } from '@/providers/graphSelection'
|
||||
import { useEvent } from '@/util/events'
|
||||
import { computed, ref } from 'vue'
|
||||
import SelectionBrush from './SelectionBrush.vue'
|
||||
|
||||
const navigator = injectGraphNavigator(true)
|
||||
const nodeSelection = injectGraphSelection(true)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useApproach } from '@/util/animation'
|
||||
import type { Vec2 } from '@/util/vec2'
|
||||
import { useApproach } from '@/composables/animation'
|
||||
import type { Vec2 } from '@/util/data/vec2'
|
||||
import { computed, watch, type Ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -5,8 +5,8 @@
|
||||
* It displays one group defined in `@/assets/icons.svg` file, specified by `variant` property.
|
||||
*/
|
||||
import icons from '@/assets/icons.svg'
|
||||
import type { URLString } from '@/util/data/urlString'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import type { URLString } from '@/util/urlString'
|
||||
|
||||
const props = defineProps<{ name: Icon | URLString; width?: number; height?: number }>()
|
||||
</script>
|
||||
|
@ -53,4 +53,3 @@ const barStyle = computed(() => {
|
||||
left: 9px;
|
||||
}
|
||||
</style>
|
||||
@/providers/guiConfig
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import VisualizationSelector from '@/components/VisualizationSelector.vue'
|
||||
import { PointerButtonMask, isTriggeredByKeyboard, usePointer } from '@/composables/events'
|
||||
import { useVisualizationConfig } from '@/providers/visualizationConfig'
|
||||
import { PointerButtonMask, isTriggeredByKeyboard, usePointer } from '@/util/events'
|
||||
import { onMounted, ref, watchEffect } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useAutoBlur } from '@/util/autoBlur'
|
||||
import type { URLString } from '@/util/data/urlString'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import type { URLString } from '@/util/urlString'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import { visIdentifierEquals, type VisualizationIdentifier } from 'shared/yjsModel'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useEvent } from '@/util/events'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import { getTextWidth } from '@/util/measurement'
|
||||
import { defineKeybinds } from '@/util/shortcuts'
|
||||
import { VisualizationContainer, useVisualizationConfig } from '@/util/visualizationBuiltins'
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import { useVisualizationConfig } from '@/providers/visualizationConfig'
|
||||
import { useEvent } from '@/util/events'
|
||||
import { getTextWidth } from '@/util/measurement'
|
||||
import { VisualizationContainer, defineKeybinds } from '@/util/visualizationBuiltins'
|
||||
import { computed, ref, watch, watchEffect, watchPostEffect } from 'vue'
|
||||
|
@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { useRaf } from '@/composables/animation'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import { useAppClass } from '@/providers/appClass'
|
||||
import { useRaf } from '@/util/animation'
|
||||
import { useEvent } from '@/util/events'
|
||||
import { Range } from '@/util/range'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { Range } from '@/util/data/range'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { uuidv4 } from 'lib0/random'
|
||||
import { nextTick } from 'process'
|
||||
import { computed, ref, shallowReactive, watchEffect, watchPostEffect } from 'vue'
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { PointerButtonMask, usePointer, useResizeObserver } from '@/util/events'
|
||||
import { PointerButtonMask, usePointer, useResizeObserver } from '@/composables/events'
|
||||
import { getTextWidth } from '@/util/measurement'
|
||||
import { computed, ref, type StyleValue } from 'vue'
|
||||
|
||||
|
3
app/gui2/src/composables/README.md
Normal file
3
app/gui2/src/composables/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Vue composables
|
||||
|
||||
This directory contains various Vue composables, mostly used to interact with the DOM.
|
@ -1,6 +1,6 @@
|
||||
import { useNavigator } from '@/util/navigator'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { useNavigator } from '@/composables/navigator'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
import { effectScope, ref } from 'vue'
|
||||
|
@ -1,3 +1,5 @@
|
||||
/** @file Vue composables for running a callback on every frame, and smooth interpolation. */
|
||||
|
||||
import { watchSourceToRef } from '@/util/reactivity'
|
||||
import { onScopeDispose, proxyRefs, ref, watch, type WatchSource } from 'vue'
|
||||
|
@ -1,15 +1,21 @@
|
||||
/** @file A Vue composable that calls one of two given callbacks, depending on whether a click is
|
||||
* a single click or a double click. */
|
||||
|
||||
/** Calls {@link onClick} if a click is a single click, or {@link onDoubleClick} if a click is
|
||||
* a double click. For this function, a double click is defined as a second click that occurs within
|
||||
* 200ms of the first click. The click count is reset to 0 upon double click, or after 200ms. */
|
||||
export function useDoubleClick<Args extends any[]>(
|
||||
onClick: (e: MouseEvent, ...args: Args) => void,
|
||||
onClick: (...args: Args) => void,
|
||||
onDoubleClick: (...args: Args) => void,
|
||||
) {
|
||||
const timeBetweenClicks = 200
|
||||
let clickCount = 0
|
||||
let singleClickTimer: ReturnType<typeof setTimeout>
|
||||
|
||||
const handleClick = (e: MouseEvent, ...args: Args) => {
|
||||
const handleClick = (...args: Args) => {
|
||||
clickCount++
|
||||
if (clickCount === 1) {
|
||||
onClick(e, ...args)
|
||||
onClick(...args)
|
||||
singleClickTimer = setTimeout(() => {
|
||||
clickCount = 0
|
||||
}, timeBetweenClicks)
|
||||
|
@ -1,5 +1,7 @@
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
/** @file Vue composables for listening to DOM events. */
|
||||
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import {
|
||||
computed,
|
||||
onScopeDispose,
|
@ -1,7 +1,9 @@
|
||||
import { useApproach } from '@/util/animation'
|
||||
import { PointerButtonMask, useEvent, usePointer, useResizeObserver } from '@/util/events'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
/** @file A Vue composable for panning and zooming a DOM element. */
|
||||
|
||||
import { useApproach } from '@/composables/animation'
|
||||
import { PointerButtonMask, useEvent, usePointer, useResizeObserver } from '@/composables/events'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { computed, proxyRefs, ref, type Ref } from 'vue'
|
||||
|
||||
function elemRect(target: Element | undefined): Rect {
|
@ -1,10 +1,12 @@
|
||||
/** @file A Vue composable for keeping track of selected DOM elements. */
|
||||
|
||||
import { selectionMouseBindings } from '@/bindings'
|
||||
import { usePointer } from '@/util/events'
|
||||
import type { NavigatorComposable } from '@/util/navigator'
|
||||
import type { Rect } from '@/util/rect'
|
||||
import type { Vec2 } from '@/util/vec2'
|
||||
import { usePointer } from '@/composables/events'
|
||||
import type { NavigatorComposable } from '@/composables/navigator'
|
||||
import type { Rect } from '@/util/data/rect'
|
||||
import type { Vec2 } from '@/util/data/vec2'
|
||||
import { type ExprId } from 'shared/yjsModel'
|
||||
import { computed, proxyRefs, reactive, ref, shallowRef } from 'vue'
|
||||
import { type ExprId } from '../../shared/yjsModel.ts'
|
||||
|
||||
export type SelectionComposable<T> = ReturnType<typeof useSelection<T>>
|
||||
export function useSelection<T>(
|
11
app/gui2/src/providers/README.md
Normal file
11
app/gui2/src/providers/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Providers
|
||||
|
||||
This folder contains [Vue providers](provider).
|
||||
|
||||
All providers MUST be at the top level - so either `./providers/myProvider.ts`,
|
||||
or `./providers/myProvider/index.ts`.
|
||||
|
||||
Each provider MAY have dependencies specific to itself, which MUST NOT be at the
|
||||
top level - so `./providers/myProvider/myDependency.ts`.
|
||||
|
||||
[provider]: https://vuejs.org/guide/components/provide-inject
|
@ -1,8 +1,3 @@
|
||||
import { GraphDb } from '@/stores/graph/graphDatabase'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { ApplicationKind, ArgumentPlaceholder } from '@/util/callTree'
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { defineComponent } from 'vue'
|
||||
import {
|
||||
Score,
|
||||
WidgetRegistry,
|
||||
@ -10,8 +5,13 @@ import {
|
||||
type WidgetDefinition,
|
||||
type WidgetInput,
|
||||
type WidgetModule,
|
||||
} from '../widgetRegistry'
|
||||
import { DisplayMode, widgetConfigurationSchema } from '../widgetRegistry/configuration'
|
||||
} from '@/providers/widgetRegistry'
|
||||
import { DisplayMode, widgetConfigurationSchema } from '@/providers/widgetRegistry/configuration'
|
||||
import { GraphDb } from '@/stores/graph/graphDatabase'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { ApplicationKind, ArgumentPlaceholder } from '@/util/callTree'
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
describe('WidgetRegistry', () => {
|
||||
function makeMockWidget<T extends WidgetInput>(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { createContextStore } from '@/providers'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { reactive, watch, type WatchSource } from 'vue'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
export { provideFn as provideAppClassSet }
|
||||
const { provideFn, injectFn: injectAppClassSet } = createContextStore('Port info', () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import { identity } from '@vueuse/core'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
interface FunctionInfo {
|
||||
callId: ExprId | undefined
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useNavigator } from '@/util/navigator'
|
||||
import { createContextStore } from '.'
|
||||
import { useNavigator } from '@/composables/navigator'
|
||||
import { createContextStore } from '@/providers'
|
||||
|
||||
export type GraphNavigator = ReturnType<typeof injectFn>
|
||||
export { injectFn as injectGraphNavigator, provideFn as provideGraphNavigator }
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { NavigatorComposable } from '@/util/navigator'
|
||||
import type { Rect } from '@/util/rect'
|
||||
import { useSelection } from '@/util/selection'
|
||||
import type { NavigatorComposable } from '@/composables/navigator'
|
||||
import { useSelection } from '@/composables/selection'
|
||||
import { createContextStore } from '@/providers'
|
||||
import type { Rect } from '@/util/data/rect'
|
||||
import type { ExprId } from 'shared/yjsModel'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
const SELECTION_BRUSH_MARGIN_PX = 6
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import { identity } from '@vueuse/core'
|
||||
import { type Ref } from 'vue'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
export interface GuiConfig {
|
||||
engine?: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { GraphNavigator } from '@/providers/graphNavigator.ts'
|
||||
import { createContextStore } from '@/providers'
|
||||
import type { GraphNavigator } from '@/providers/graphNavigator'
|
||||
import { watch, type WatchSource } from 'vue'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
export { injectFn as injectInteractionHandler, provideFn as provideInteractionHandler }
|
||||
const { provideFn, injectFn } = createContextStore(
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import { GetUsageKey } from '@/providers/widgetUsageInfo'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { identity } from '@vueuse/core'
|
||||
import { createContextStore } from '.'
|
||||
import { GetUsageKey } from './widgetUsageInfo'
|
||||
|
||||
interface PortInfo {
|
||||
portId: string
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import type { URLString } from '@/util/data/urlString'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import type { URLString } from '@/util/urlString'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import type { VisualizationIdentifier } from 'shared/yjsModel'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import { type WidgetConfiguration } from '@/providers/widgetRegistry/configuration'
|
||||
import type { GraphDb } from '@/stores/graph/graphDatabase'
|
||||
import { computed, shallowReactive, type Component, type PropType } from 'vue'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
export type WidgetComponent<T extends WidgetInput> = Component<WidgetProps<T>>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { computed, proxyRefs, type Ref } from 'vue'
|
||||
import { createContextStore } from '.'
|
||||
|
||||
export { injectFn as injectWidgetTree, provideFn as provideWidgetTree }
|
||||
const { provideFn, injectFn } = createContextStore(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createContextStore } from '@/providers'
|
||||
import type { WidgetComponent, WidgetInput } from '@/providers/widgetRegistry'
|
||||
import { identity } from '@vueuse/core'
|
||||
import { createContextStore } from '.'
|
||||
import type { WidgetComponent, WidgetInput } from './widgetRegistry'
|
||||
|
||||
export { injectFn as injectWidgetUsageInfo, provideFn as provideWidgetUsageInfo }
|
||||
const { provideFn, injectFn } = createContextStore('Widget usage info', identity<WidgetUsageInfo>)
|
||||
|
11
app/gui2/src/stores/README.md
Normal file
11
app/gui2/src/stores/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Stores
|
||||
|
||||
This folder contains [Pinia] stores.
|
||||
|
||||
All stores MUST be at the top level - so either `./stores/myStore.ts`, or
|
||||
`./stores/myStore/index.ts`.
|
||||
|
||||
Each store MAY have dependencies specific to itself, which MUST NOT be at the
|
||||
top level - so `./stores/myStore/myDependency.ts`.
|
||||
|
||||
[Pinia]: https://pinia.vuejs.org/
|
@ -1,4 +1,4 @@
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import type { StackItem } from 'shared/languageServerTypes'
|
||||
import { reactive } from 'vue'
|
||||
import { Awareness as YjsAwareness } from 'y-protocols/awareness'
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { GraphDb } from '@/stores/graph/graphDatabase'
|
||||
import { Ast } from '@/util/ast'
|
||||
import assert from 'assert'
|
||||
import { IdMap, type ExprId } from 'shared/yjsModel'
|
||||
import { expect, test } from 'vitest'
|
||||
import { GraphDb } from '../graphDatabase'
|
||||
|
||||
test('Reading graph from definition', () => {
|
||||
const code = 'function a =\n node1 = a + 4\n node2 = node1 + 4'
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { ComputedValueRegistry, type ExpressionInfo } from '@/stores/project/computedValueRegistry'
|
||||
import { SuggestionDb, groupColorStyle, type Group } from '@/stores/suggestionDatabase'
|
||||
import type { SuggestionEntry } from '@/stores/suggestionDatabase/entry'
|
||||
import { arrayEquals, byteArraysEqual, tryGetIndex } from '@/util/array'
|
||||
import { Ast, RawAst, RawAstExtended } from '@/util/ast'
|
||||
import { AliasAnalyzer } from '@/util/ast/aliasAnalysis'
|
||||
import { colorFromString } from '@/util/colors'
|
||||
import { MappedKeyMap, MappedSet } from '@/util/containers'
|
||||
import { arrayEquals, byteArraysEqual, tryGetIndex } from '@/util/data/array'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { ReactiveDb, ReactiveIndex, ReactiveMapping } from '@/util/database/reactiveDb'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import * as set from 'lib0/set'
|
||||
import { methodPointerEquals, type MethodCall } from 'shared/languageServerTypes'
|
||||
import {
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
type SuggestionEntry,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import {
|
||||
identifierUnchecked,
|
||||
normalizeQualifiedName,
|
||||
@ -19,7 +20,6 @@ import {
|
||||
type Identifier,
|
||||
type QualifiedName,
|
||||
} from '@/util/qualifiedName'
|
||||
import { unwrap } from '@/util/result'
|
||||
|
||||
// ========================
|
||||
// === Imports analysis ===
|
||||
|
@ -11,9 +11,9 @@ import { useProjectStore } from '@/stores/project'
|
||||
import { useSuggestionDbStore } from '@/stores/suggestionDatabase'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { useObserveYjs } from '@/util/crdt'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { Rect } from '@/util/rect'
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { Rect } from '@/util/data/rect'
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { StackItem } from 'shared/languageServerTypes'
|
||||
import {
|
||||
|
@ -3,6 +3,9 @@ import { Awareness } from '@/stores/awareness'
|
||||
import { ComputedValueRegistry } from '@/stores/project/computedValueRegistry'
|
||||
import { VisualizationDataRegistry } from '@/stores/project/visualizationDataRegistry'
|
||||
import { attachProvider, useObserveYjs } from '@/util/crdt'
|
||||
import { nextEvent } from '@/util/data/observable'
|
||||
import { isSome, type Opt } from '@/util/data/opt'
|
||||
import { Err, Ok, type Result } from '@/util/data/result'
|
||||
import { ReactiveMapping } from '@/util/database/reactiveDb'
|
||||
import {
|
||||
AsyncQueue,
|
||||
@ -10,10 +13,7 @@ import {
|
||||
createWebsocketClient,
|
||||
rpcWithRetries as lsRpcWithRetries,
|
||||
} from '@/util/net'
|
||||
import { nextEvent } from '@/util/observable'
|
||||
import { isSome, type Opt } from '@/util/opt'
|
||||
import { tryQualifiedName } from '@/util/qualifiedName'
|
||||
import { Err, Ok, type Result } from '@/util/result'
|
||||
import { Client, RequestManager } from '@open-rpc/client-js'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import * as array from 'lib0/array'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { ExecutionContext } from '@/stores/project'
|
||||
import { Err, Ok, type Result } from '@/util/result'
|
||||
import { Err, Ok, type Result } from '@/util/data/result'
|
||||
import { OutboundPayload, VisualizationUpdate } from 'shared/binaryProtocol'
|
||||
import type { DataServer } from 'shared/dataServer'
|
||||
import type {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { SuggestionDb, type Group } from '@/stores/suggestionDatabase'
|
||||
import { SuggestionKind, entryQn, type SuggestionEntry } from '@/stores/suggestionDatabase/entry'
|
||||
import { applyUpdates } from '@/stores/suggestionDatabase/lsUpdate'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import { parseDocs } from '@/util/docParser'
|
||||
import { tryIdentifier, tryQualifiedName, type QualifiedName } from '@/util/qualifiedName'
|
||||
import { unwrap } from '@/util/result'
|
||||
import * as lsTypes from 'shared/languageServerTypes/suggestions'
|
||||
import { expect, test } from 'vitest'
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import type { Group } from '@/stores/suggestionDatabase'
|
||||
import { findIndexOpt } from '@/util/array'
|
||||
import { findIndexOpt } from '@/util/data/array'
|
||||
import { isSome, type Opt } from '@/util/data/opt'
|
||||
import { unwrap } from '@/util/data/result'
|
||||
import { parseDocs, type Doc } from '@/util/docParser'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import { isSome, type Opt } from '@/util/opt'
|
||||
import { tryQualifiedName, type QualifiedName } from '@/util/qualifiedName'
|
||||
import { unwrap } from '@/util/result'
|
||||
|
||||
export interface DocumentationData {
|
||||
documentation: Doc.Section[]
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { entryQn, type SuggestionEntry, type SuggestionId } from '@/stores/suggestionDatabase/entry'
|
||||
import { applyUpdates, entryFromLs } from '@/stores/suggestionDatabase/lsUpdate'
|
||||
import { type Opt } from '@/util/data/opt'
|
||||
import { ReactiveDb, ReactiveIndex } from '@/util/database/reactiveDb'
|
||||
import { AsyncQueue, rpcWithRetries } from '@/util/net'
|
||||
import { type Opt } from '@/util/opt'
|
||||
import { qnJoin, qnParent, tryQualifiedName, type QualifiedName } from '@/util/qualifiedName'
|
||||
import { defineStore } from 'pinia'
|
||||
import { LanguageServer } from 'shared/languageServer'
|
||||
|
@ -11,9 +11,10 @@ import {
|
||||
type Typename,
|
||||
} from '@/stores/suggestionDatabase/entry'
|
||||
import { assert, assertNever } from '@/util/assert'
|
||||
import { type Opt } from '@/util/data/opt'
|
||||
import { Err, Ok, withContext, type Result } from '@/util/data/result'
|
||||
import type { Doc } from '@/util/docParser'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import { type Opt } from '@/util/opt'
|
||||
import {
|
||||
normalizeQualifiedName,
|
||||
qnJoin,
|
||||
@ -23,7 +24,6 @@ import {
|
||||
type Identifier,
|
||||
type QualifiedName,
|
||||
} from '@/util/qualifiedName'
|
||||
import { Err, Ok, withContext, type Result } from '@/util/result'
|
||||
import * as lsTypes from 'shared/languageServerTypes/suggestions'
|
||||
|
||||
interface UnfinishedEntry {
|
||||
|
@ -17,8 +17,8 @@ import type {
|
||||
import Compiler from '@/stores/visualization/compiler?worker'
|
||||
import { VisualizationModule } from '@/stores/visualization/runtimeTypes'
|
||||
import { assertNever } from '@/util/assert'
|
||||
import { toError } from '@/util/error'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { toError } from '@/util/data/error'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { defineKeybinds } from '@/util/shortcuts'
|
||||
import { VisualizationContainer, useVisualizationConfig } from '@/util/visualizationBuiltins'
|
||||
import { Error as DataError } from 'shared/binaryProtocol'
|
||||
|
@ -21,8 +21,10 @@ import {
|
||||
type VisualizationId,
|
||||
} from '@/stores/visualization/metadata'
|
||||
import type { VisualizationModule } from '@/stores/visualization/runtimeTypes'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { isUrlString } from '@/util/data/urlString'
|
||||
import { isIconName } from '@/util/iconName'
|
||||
import { rpcWithRetries } from '@/util/net'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Event as LSEvent, VisualizationConfiguration } from 'shared/languageServerTypes'
|
||||
import type { ExprId, VisualizationIdentifier } from 'shared/yjsModel'
|
||||
@ -226,7 +228,8 @@ export const useVisualizationStore = defineStore('visualization', () => {
|
||||
}
|
||||
|
||||
function icon(type: VisualizationIdentifier) {
|
||||
return metadata.get(toVisualizationId(type))?.icon
|
||||
const icon = metadata.get(toVisualizationId(type))?.icon
|
||||
return icon && (isIconName(icon) || isUrlString(icon)) ? icon : undefined
|
||||
}
|
||||
|
||||
function get(meta: VisualizationIdentifier, ignoreCache = false) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { VisualizationModule } from '@/stores/visualization/runtimeTypes'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { ReactiveDb, ReactiveIndex } from '@/util/database/reactiveDb'
|
||||
import type { Opt } from '@/util/opt'
|
||||
import type { VisualizationIdentifier } from 'shared/yjsModel'
|
||||
|
||||
export interface VisualizationMetadata
|
||||
|
@ -1,6 +1,5 @@
|
||||
import iconNames from '@/util/iconList.json'
|
||||
import type { Icon } from '@/util/iconName'
|
||||
import type { URLString } from '@/util/urlString'
|
||||
import { isUrlString } from '@/util/data/urlString'
|
||||
import { isIconName } from '@/util/iconName'
|
||||
import type { DefineComponent, PropType } from 'vue'
|
||||
import * as z from 'zod'
|
||||
|
||||
@ -42,8 +41,7 @@ export const VisualizationModule = z.object({
|
||||
icon: z
|
||||
.string()
|
||||
.transform((s) => {
|
||||
if (iconNames.includes(s)) return s as Icon
|
||||
else if (s.includes(':')) return s as URLString
|
||||
if (isIconName(s) || isUrlString(s)) return s
|
||||
console.warn(`Invalid icon name '${s}'`)
|
||||
return undefined
|
||||
})
|
||||
|
4
app/gui2/src/util/README.md
Normal file
4
app/gui2/src/util/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Utilities
|
||||
|
||||
This folder contains code (mostly utility functions) that are not related to any
|
||||
specific part of the UI.
|
@ -1,4 +1,4 @@
|
||||
import { partitionPoint } from '@/util/array'
|
||||
import { partitionPoint } from '@/util/data/array'
|
||||
import { fc, test as fcTest } from '@fast-check/vitest'
|
||||
import { expect } from 'vitest'
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MultiRange, Range } from '@/util/range'
|
||||
import { MultiRange, Range } from '@/util/data/range'
|
||||
import { expect, test } from 'vitest'
|
||||
|
||||
function r(...r: [start: number, end: number][]) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { LazySyncEffectSet } from '@/util/reactivity'
|
||||
import { expect, test, vi } from 'vitest'
|
||||
import { nextTick, reactive, ref } from 'vue'
|
||||
import { LazySyncEffectSet } from '../reactivity'
|
||||
|
||||
test('LazySyncEffectSet', async () => {
|
||||
const lazySet = new LazySyncEffectSet()
|
||||
|
@ -25,12 +25,11 @@
|
||||
* All unannotated identifiers are assumed to preexist in the environment (captured from an external scope or imports).
|
||||
*/
|
||||
|
||||
import type { ContentRange } from '@/../../../../shared/yjsModel'
|
||||
import { assertDefined } from '@/util/assert'
|
||||
import { AliasAnalyzer } from '@/util/ast/aliasAnalysis'
|
||||
import { MappedKeyMap, MappedSet } from '@/util/containers'
|
||||
import { IdMap, type ContentRange } from 'shared/yjsModel'
|
||||
import { expect, test } from 'vitest'
|
||||
import { IdMap } from '../../../../shared/yjsModel'
|
||||
import { AliasAnalyzer } from '../aliasAnalysis'
|
||||
|
||||
/** The type of annotation. */
|
||||
enum AnnotationType {
|
||||
@ -57,7 +56,7 @@ function parseAnnotations(annotatedCode: string): {
|
||||
unannotatedCode: string
|
||||
annotations: MappedKeyMap<ContentRange, Annotation>
|
||||
} {
|
||||
const annotations = new MappedKeyMap(IdMap.keyForRange)
|
||||
const annotations = new MappedKeyMap<ContentRange, Annotation>(IdMap.keyForRange)
|
||||
|
||||
// Iterate over all annotations (either bindings or usages).
|
||||
// I.e. we want to cover both `«1,x»` and `»1,x«` cases, while keeping the track of the annotation type.
|
||||
@ -69,7 +68,14 @@ function parseAnnotations(annotatedCode: string): {
|
||||
|
||||
const unannotatedCode = annotatedCode.replace(
|
||||
annotationRegex,
|
||||
(match, bindingPrefix, bindingName, usagePrefix, usageName, offset) => {
|
||||
(
|
||||
match,
|
||||
bindingPrefix: string | undefined,
|
||||
bindingName: string | undefined,
|
||||
usagePrefix: string | undefined,
|
||||
usageName: string | undefined,
|
||||
offset: number,
|
||||
) => {
|
||||
console.log(`Processing annotated identifier ${match}.`)
|
||||
|
||||
// Sanity check: either both binding prefix and name are present, or both usage prefix and name are present.
|
||||
@ -78,13 +84,13 @@ function parseAnnotations(annotatedCode: string): {
|
||||
expect(usagePrefix != null).toBe(usageName != null)
|
||||
expect(bindingPrefix != null).not.toBe(usagePrefix != null)
|
||||
|
||||
const id = parseInt(bindingPrefix ?? usagePrefix, 10)
|
||||
const name = bindingName ?? usageName
|
||||
const id = parseInt(bindingPrefix ?? usagePrefix ?? '0', 10)
|
||||
const name = bindingName ?? usageName ?? ''
|
||||
const kind = bindingPrefix != null ? AnnotationType.Binding : AnnotationType.Usage
|
||||
|
||||
const start = offset - accumulatedOffset
|
||||
const end = start + name.length
|
||||
const range = [start, end]
|
||||
const range: ContentRange = [start, end]
|
||||
|
||||
const annotation = new Annotation(kind, id)
|
||||
accumulatedOffset += match.length - name.length
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { Token, Tree } from '@/generated/ast'
|
||||
import type { LazyObject } from '@/util/parserSupport'
|
||||
import { assert, expect, test } from 'vitest'
|
||||
import {
|
||||
astContainingChar,
|
||||
childrenAstNodes,
|
||||
@ -11,7 +9,9 @@ import {
|
||||
readAstSpan,
|
||||
readTokenSpan,
|
||||
walkRecursive,
|
||||
} from '..'
|
||||
} from '@/util/ast'
|
||||
import type { LazyObject } from '@/util/parserSupport'
|
||||
import { assert, expect, test } from 'vitest'
|
||||
|
||||
function validateSpans(obj: LazyObject, initialPos?: number): number {
|
||||
const state = { pos: initialPos ?? 0 }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { SuggestionKind, type SuggestionEntry } from '@/stores/suggestionDatabase/entry'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { ArgumentApplication, ArgumentPlaceholder } from '@/util/callTree'
|
||||
import { isSome } from '@/util/opt'
|
||||
import { isSome } from '@/util/data/opt'
|
||||
import { type Identifier, type QualifiedName } from '@/util/qualifiedName'
|
||||
import type { MethodCall } from 'shared/languageServerTypes'
|
||||
import { assert, expect, test } from 'vitest'
|
||||
|
@ -1,12 +1,11 @@
|
||||
import * as RawAst from '@/generated/ast'
|
||||
import { parseEnso } from '@/util/ast'
|
||||
import { AstExtended as RawAstExtended } from '@/util/ast/extended'
|
||||
import { Err, Ok, type Result } from '@/util/data/result'
|
||||
import type { LazyObject } from '@/util/parserSupport'
|
||||
import { Err, Ok, type Result } from '@/util/result'
|
||||
import * as random from 'lib0/random'
|
||||
import { IdMap, type ExprId } from 'shared/yjsModel'
|
||||
import { reactive } from 'vue'
|
||||
import type { ExprId } from '../../../shared/yjsModel'
|
||||
import { IdMap } from '../../../shared/yjsModel'
|
||||
|
||||
interface Module {
|
||||
get(id: AstId): Ast | null
|
||||
|
@ -7,11 +7,9 @@ import {
|
||||
readAstOrTokenSpan,
|
||||
readTokenSpan,
|
||||
} from '@/util/ast'
|
||||
|
||||
import { MappedKeyMap, MappedSet, NonEmptyStack } from '@/util/containers'
|
||||
import type { LazyObject } from '@/util/parserSupport.ts'
|
||||
import type { ContentRange } from '../../../shared/yjsModel'
|
||||
import { IdMap, rangeIsBefore } from '../../../shared/yjsModel'
|
||||
import type { LazyObject } from '@/util/parserSupport'
|
||||
import { IdMap, rangeIsBefore, type ContentRange } from 'shared/yjsModel'
|
||||
|
||||
const ACCESSOR_OPERATOR = '.'
|
||||
|
||||
|
@ -1,11 +1,6 @@
|
||||
import * as Ast from '@/generated/ast'
|
||||
import { Token, Tree } from '@/generated/ast'
|
||||
import { assert } from '@/util/assert'
|
||||
import * as encoding from 'lib0/encoding'
|
||||
import { digest } from 'lib0/hash/sha256'
|
||||
import * as map from 'lib0/map'
|
||||
import type { ContentRange, ExprId, IdMap } from 'shared/yjsModel'
|
||||
import { markRaw } from 'vue'
|
||||
import {
|
||||
childrenAstNodesOrTokens,
|
||||
debugAst,
|
||||
@ -15,8 +10,13 @@ import {
|
||||
visitGenerator,
|
||||
visitRecursive,
|
||||
walkRecursive,
|
||||
} from '.'
|
||||
import type { Opt } from '../opt'
|
||||
} from '@/util/ast'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import * as encoding from 'lib0/encoding'
|
||||
import * as sha256 from 'lib0/hash/sha256'
|
||||
import * as map from 'lib0/map'
|
||||
import type { ContentRange, ExprId, IdMap } from 'shared/yjsModel'
|
||||
import { markRaw } from 'vue'
|
||||
|
||||
type ExtractType<V, T> = T extends ReadonlyArray<infer Ts>
|
||||
? Extract<V, { type: Ts }>
|
||||
@ -218,7 +218,7 @@ class AstExtendedCtx<HasIdMap extends boolean> {
|
||||
getHash(ast: AstExtended<Tree | Token, boolean>) {
|
||||
const key = AstExtendedCtx.getHashKey(ast)
|
||||
return map.setIfUndefined(this.contentHashes, key, () =>
|
||||
digest(
|
||||
sha256.digest(
|
||||
encoding.encode((encoder) => {
|
||||
const whitespace = ast.whitespaceLength()
|
||||
encoding.writeUint32(encoder, whitespace)
|
||||
|
@ -1,12 +1,12 @@
|
||||
import * as RawAst from '@/generated/ast'
|
||||
import { assert } from '@/util/assert'
|
||||
import * as Ast from '@/util/ast/abstract'
|
||||
import { AstExtended as RawAstExtended } from '@/util/ast/extended'
|
||||
import { isResult, mapOk } from '@/util/data/result'
|
||||
import { parse } from '@/util/ffi'
|
||||
import { LazyObject, LazySequence } from '@/util/parserSupport'
|
||||
import { isResult, mapOk } from '@/util/result'
|
||||
import * as map from 'lib0/map'
|
||||
import type { ContentRange } from 'shared/yjsModel'
|
||||
import { AstExtended as RawAstExtended } from './extended'
|
||||
|
||||
export { Ast, RawAst, RawAstExtended }
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { assert } from '@/util/assert'
|
||||
import { RawAst, RawAstExtended } from '@/util/ast'
|
||||
import { zip } from '@/util/iterable'
|
||||
import { zip } from '@/util/data/iterable'
|
||||
import { mapIterator } from 'lib0/iterator'
|
||||
|
||||
/** An operand of one of the applications inside `GeneralOprApp` */
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useEvent } from '@/util/events'
|
||||
import { useEvent } from '@/composables/events'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
export function useAutoBlur(root: Ref<HTMLElement | SVGElement | MathMLElement | undefined>) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { ForcePort } from '@/providers/portInfo'
|
||||
import type { SuggestionEntry, SuggestionEntryArgument } from '@/stores/suggestionDatabase/entry'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { tryGetIndex } from '@/util/data/array'
|
||||
import type { MethodCall } from 'shared/languageServerTypes'
|
||||
import { tryGetIndex } from './array'
|
||||
import { Ast } from './ast'
|
||||
|
||||
export const enum ApplicationKind {
|
||||
Prefix,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { isNone, isSome, type Opt } from '@/util/opt'
|
||||
import { isNone, isSome, type Opt } from '@/util/data/opt'
|
||||
|
||||
/**
|
||||
* Compare two optional numbers. Returns a comparision result like specified for `sort`
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { NonEmptyArray } from '@/util/array.ts'
|
||||
import { assertDefined, assertEqual } from '@/util/assert'
|
||||
import type { NonEmptyArray } from '@/util/data/array'
|
||||
import { mapIterator } from 'lib0/iterator'
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Opt } from '@/util/opt'
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
import { watchEffect, type Ref } from 'vue'
|
||||
import type { Awareness } from 'y-protocols/awareness'
|
||||
import { WebsocketProvider } from 'y-websocket'
|
||||
|
7
app/gui2/src/util/data/README.md
Normal file
7
app/gui2/src/util/data/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Data structures
|
||||
|
||||
This folder contains:
|
||||
|
||||
- classes defining data structures
|
||||
- branded types (newtypes) for specific data types
|
||||
- utility functions for data structures
|
@ -1,4 +1,6 @@
|
||||
import type { Opt } from './opt'
|
||||
/** @file Functions for querying and manipulating arrays. */
|
||||
|
||||
import type { Opt } from '@/util/data/opt'
|
||||
|
||||
/** An array that has at least one element present at all times. */
|
||||
export type NonEmptyArray<T> = [T, ...T[]]
|
@ -1,3 +1,5 @@
|
||||
/** @file Functions for creating errors. */
|
||||
|
||||
/** Returns {@link Error}s as-is, wraps all other values in an {@link Error}. */
|
||||
export function toError(error: unknown) {
|
||||
return error instanceof Error ? error : new Error(String(error))
|
@ -1,3 +1,5 @@
|
||||
/** @file Functions for manipulating {@link Iterable}s. */
|
||||
|
||||
export function* empty(): Generator<never> {}
|
||||
|
||||
export function* range(start: number, stop: number, step = start <= stop ? 1 : -1) {
|
@ -1,3 +1,5 @@
|
||||
/** Functions for querying {@link ObservableV2}s. */
|
||||
|
||||
import type { ObservableV2 } from 'lib0/observable'
|
||||
|
||||
export type Events<O extends ObservableV2<any>> = O extends ObservableV2<infer E> ? E : never
|
21
app/gui2/src/util/data/opt.ts
Normal file
21
app/gui2/src/util/data/opt.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/** @file A value that may be `null` or `undefined`. */
|
||||
|
||||
/** Optional value type. This is a replacement for `T | null | undefined` that is more
|
||||
* convenient to use. We do not select a single value to represent "no value", because we are using
|
||||
* libraries that disagree whether `null` (e.g. Yjs) or `undefined` (e.g. Vue) should be used for
|
||||
* that purpose. We want to be compatible with both without needless conversions. In our own code,
|
||||
* we should return `undefined` for "no value", since that is the default value for empty or no
|
||||
* `return` expression. In order to test whether an `Opt<T>` is defined or not, use `x == null` or
|
||||
* `isSome` function.
|
||||
*
|
||||
* Note: For JSON-serialized data, prefer explicit `null` over `undefined`, since `undefined` is
|
||||
* not serializable. Alternatively, use optional field syntax (e.g. `{ x?: number }`). */
|
||||
export type Opt<T> = T | null | undefined
|
||||
|
||||
export function isSome<T>(value: Opt<T>): value is T {
|
||||
return value != null
|
||||
}
|
||||
|
||||
export function isNone(value: Opt<any>): value is null | undefined {
|
||||
return value == null
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import { partitionPoint } from '@/util/array'
|
||||
/** @file Ranges between two numbers, and sets of multiple ranges with gaps between. */
|
||||
|
||||
import { partitionPoint } from '@/util/data/array'
|
||||
|
||||
export interface RangeWithMatch {
|
||||
readonly start: number
|
@ -1,8 +1,8 @@
|
||||
import { Vec2 } from '@/util/vec2'
|
||||
/** @file Axis-aligned rectangle. Defined in terms of a top-left point and a size. */
|
||||
|
||||
/**
|
||||
* Axis-aligned rectangle. Defined in terms of a top-left point and a size.
|
||||
*/
|
||||
import { Vec2 } from '@/util/data/vec2'
|
||||
|
||||
/** Axis-aligned rectangle. Defined in terms of a top-left point and a size. */
|
||||
export class Rect {
|
||||
constructor(
|
||||
readonly pos: Vec2,
|
@ -1,4 +1,7 @@
|
||||
import { isSome, type Opt } from '@/util/opt'
|
||||
/** @file A generic type that can either hold a value representing a successful result,
|
||||
* or an error. */
|
||||
|
||||
import { isSome, type Opt } from '@/util/data/opt'
|
||||
|
||||
export type Result<T = undefined, E = string> =
|
||||
| { ok: true; value: T }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user