Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F969353
jdd-page.tsx
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
jdd-page.tsx
View Options
import
type
{
Component
,
RawJDDocument
}
from
"@sealcode/jdd"
;
import
{
documentContainerFromParsed
}
from
"@sealcode/jdd"
;
import
{
render
,
renderEarlyAssets
}
from
"@sealcode/jdd"
;
import
{
StatefulPage
}
from
"@sealcode/sealgen"
;
import
{
hasFieldOfType
,
hasShape
,
predicates
}
from
"@sealcode/ts-predicates"
;
import
type
{
BaseContext
}
from
"koa"
;
import
type
{
FlatTemplatable
,
Templatable
}
from
"tempstream"
;
import
{
tempstream
,
TempstreamJSX
}
from
"tempstream"
;
import
html
,
{
defaultHead
}
from
"../../html.js"
;
import
{
registry
}
from
"../../jdd-components/components.js"
;
import
{
makeJDDContext
}
from
"../../jdd-context.js"
;
import
{
ComponentInput
}
from
"./component-input.js"
;
import
{
ComponentPreviewActions
}
from
"./component-preview-actions.js"
;
export
const
actionName
=
"Components"
;
export
type
JDDPageState
=
{
components
:
RawJDDocument
;
preview_size
?:
string
;
};
export
default
abstract
class
JDDPage
extends
StatefulPage
<
JDDPageState
,
typeof
ComponentPreviewActions
>
{
actions
=
ComponentPreviewActions
;
previewSizes
=
[
"320"
,
"600"
,
"800"
,
"1024"
,
"1300"
,
"1920"
];
getRegistryCompoments
()
{
return
registry
.
getAll
();
}
async
getInitialState
(
ctx
:
BaseContext
)
{
const
[
component_name
,
component
]
=
Object
.
entries
(
this
.
getRegistryCompoments
()
)[
0
];
const
initial_state
=
{
components
:
[
{
component_name
:
component_name
,
args
:
await
component
.
getExampleValues
(
makeJDDContext
(
ctx
)),
},
],
};
return
initial_state
;
}
wrapInLayout
(
ctx
:
BaseContext
,
content
:
Templatable
,
state
:
JDDPageState
)
:
Templatable
{
return
html
(
ctx
,
"Components"
,
content
,
{
morphing
:
true
,
preserveScroll
:
true
,
autoRefreshCSS
:
true
,
navbar
:
()
=>
``
,
},
(...
args
)
=>
tempstream
`
${
defaultHead
(...
args
)
}${
renderEarlyAssets
(
registry
,
documentContainerFromParsed
(
state
.
components
),
makeJDDContext
(
ctx
)
)
}
`
);
}
async
preprocessOverrides
(
_ctx
:
BaseContext
,
state
:
JDDPageState
,
overrides
:
Record
<
string
,
unknown
>
)
{
const
jdd_context
=
makeJDDContext
(
_ctx
);
if
(
!
hasFieldOfType
(
"components"
,
overrides
,
predicates
.
array
(
predicates
.
shape
({
args
:
predicates
.
object
,
})
)
)
)
{
return
{};
}
for
(
const
[
component_index
,
{
component_name
}]
of
Object
.
entries
(
state
.
components
))
{
const
component
=
registry
.
get
(
component_name
);
if
(
!
component
)
{
throw
new
Error
(
`Unknown component:
${
component_name
}
`
);
}
const
overrides_for_component
=
overrides
.
components
[
parseInt
(
component_index
)];
const
promises
=
Object
.
entries
(
component
.
getArguments
()).
map
(
async
([
arg_name
,
arg
])
=>
{
const
value
=
overrides_for_component
.
args
[
arg_name
];
if
(
value
)
{
const
new_value
=
await
arg
.
receivedToParsed
(
jdd_context
,
value
);
overrides_for_component
.
args
[
arg_name
]
=
new_value
;
}
}
);
// eslint-disable-next-line no-await-in-loop
await
Promise
.
all
(
promises
);
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return
overrides
;
}
// eslint-disable-next-line no-unused-vars
abstract
renderParameterButtons
(
_state
:
JDDPageState
)
:
FlatTemplatable
;
renderComponentArgs
<
C
extends
Component
>
(
ctx
:
BaseContext
,
state
:
JDDPageState
,
component
:
C
,
args
:
Record
<
string
,
unknown
>
,
index
:
number
)
{
const
jdd_context
=
makeJDDContext
(
ctx
);
return
(
<
fieldset
class
=
"component-preview-parameters"
>
<
legend
>
Parameters
<
/legend>
{
Object
.
entries
(
component
.
getArguments
()).
map
(
async
([
arg_name
,
arg
])
=>
(
<
ComponentInput
{...{
state
,
arg_path
:
[
"components"
,
index
.
toString
(),
"args"
,
arg_name
],
ctx
,
arg
,
value
:
args
[
arg_name
]
===
undefined
?
await
arg
.
getExampleValue
(
jdd_context
)
:
args
[
arg_name
],
onblur
:
this
.
rerender
(),
page
:
this
,
}}
/>
))}
<
input
type
=
"submit"
value
=
"Preview"
/>
<
/fieldset>
);
}
renderComponentBlock
(
ctx
:
BaseContext
,
state
:
JDDPageState
,
{
component_name
,
args
:
component_args
,
}
:
{
component_name
:
string
;
args
:
Record
<
string
,
unknown
>
;
},
component_index
:
number
)
{
const
component
=
registry
.
get
(
component_name
);
if
(
!
component
)
{
return
null
;
}
return
this
.
renderComponentArgs
(
ctx
,
state
,
component
,
component_args
,
component_index
);
}
async
serializeState
(
ctx
:
BaseContext
,
state
:
JDDPageState
)
{
const
serialized_components
=
await
Promise
.
all
(
state
.
components
.
map
(
async
({
component_name
,
args
})
=>
{
const
component
=
registry
.
get
(
component_name
);
const
single_result
=
{
component_name
,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
args
:
component
?
await
component
.
convertParsedToStorage
(
makeJDDContext
(
ctx
),
args
)
:
{},
};
return
single_result
;
})
);
const
serialized_state
=
JSON
.
stringify
({
components
:
serialized_components
});
return
serialized_state
;
}
async
deserializeState
(
ctx
:
BaseContext
,
state_string
:
string
)
{
const
jdd_context
=
makeJDDContext
(
ctx
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const
raw
=
JSON
.
parse
(
state_string
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
const
components_storage
=
raw
.
components
;
if
(
!
Array
.
isArray
(
components_storage
))
{
throw
new
Error
(
"'components' key is not an array, got ${components_storage}"
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const
components_parsed
=
await
Promise
.
all
(
components_storage
.
map
(
async
(
entry
)
=>
{
if
(
!
hasShape
(
{
component_name
:
predicates
.
string
,
args
:
predicates
.
object
,
},
entry
)
)
{
throw
new
Error
(
`Expected components[] items to be objects with 'component_name' and 'args' keys, got
${
entry
}
`
);
}
const
{
component_name
,
args
}
=
entry
;
const
component
=
registry
.
get
(
component_name
);
if
(
!
component
)
{
throw
new
Error
(
"Unknown component: ${component_name}"
);
}
return
{
component_name
,
args
:
await
component
.
convertStorageToParsed
(
jdd_context
,
args
),
};
})
);
const
result
=
{
components
:
components_parsed
};
return
result
;
}
render
(
ctx
:
BaseContext
,
state
:
JDDPageState
)
{
return
(
<
div
class
=
"two-column"
id
=
"component-debugger"
style
=
"--resizable-column-width: 50vw"
data
-
controller
=
"component-debugger"
>
<
div
class
=
"component-arguments"
>
{
this
.
renderParameterButtons
(
state
)}
{
state
.
components
.
map
((
component
,
component_index
)
=>
this
.
renderComponentBlock
(
ctx
,
state
,
component
,
component_index
)
)}
<
code
>
{
this
.
serializeState
(
ctx
,
state
)}
<
/code>
<
/div>
<
div
class
=
"resize-gutter"
data
-
component
-
debugger
-
target
=
"gutter"
><
/div>
<
div
class
=
"component-preview"
data
-
component
-
debugger
-
target
=
"preview"
>
<
fieldset
>
<
legend
>
Preview
{
" "
}
<
span
data
-
component
-
debugger
-
target
=
"component-width"
><
/span>
<
select
name
=
"size"
autocomplete
=
"off"
class
=
"component-preview-size-select"
data
-
component
-
debugger
-
target
=
"size-select"
data
-
action
=
"change->component-debugger#handleWidthDropdown"
>
{
this
.
previewSizes
.
map
((
size
)
=>
(
<
option
value
=
{
size
}
selected
=
{
size
===
(
state
.
preview_size
||
"800"
)}
>
{
`
${
size
}
px`
}
<
/option>
))}
<
/select>
<
noscript
>
{
this
.
makeActionButton
(
state
,
"change_size"
)}
<
/noscript>
<
/legend>
{
render
(
registry
,
documentContainerFromParsed
(
state
.
components
),
makeJDDContext
(
ctx
)
)}
<
/fieldset>
{
/* HTML */
`<script>
(function () {
const gutter = document.querySelector(".resize-gutter");
})();
</script>`
}
<
/div>
<
/div>
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Fri, Nov 22, 20:14 (19 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547731
Default Alt Text
jdd-page.tsx (7 KB)
Attached To
Mode
rPLAY Sealious playground
Attached
Detach File
Event Timeline
Log In to Comment