![Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility](https://cdn.sanity.io/images/cgdhsj6q/production/97774ea8c88cc8f4bed2766c31994ebc38116948-1664x1366.png?w=400&fit=max&auto=format)
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
@benev/slate
Advanced tools
@benev/slate
🚧 prerelease wip under constructon subject to change
npm i @benev/slate
import {prepare_frontend, Context} from "@benev/slate"
export const {carbon, oxygen, obsidian, quartz} = (
prepare_frontend(new class extends Context {
theme = css`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
`
})
)
import {html, css} from "@benev/slate"
this is how you create web components that are custom html elements.
they can be used in plain html <my-oxygen></my-oxygen>
.
export const MyOxygen = oxygen(use => {
const count = use.signal(0)
const increment = () => count.value++
return html`
<span>${count}</span>
<button @click=${increment}>increment</button>
`
})
const styles = css`span {color: yellow}`
export const MyCarbon = carbon({styles}, use => {
const count = use.signal(0)
const increment = () => count.value++
return html`
<span>${count}</span>
<button @click=${increment}>increment</button>
`
})
import {register_to_dom} from "@benev/slate"
register_to_dom({
MyOxygen,
MyCarbon,
})
CamelCase
to kebab-case
<section>
<my-oxygen></my-oxygen>
<my-carbon></my-carbon>
</section>
views are like components, but they are not custom html elements.
what's great about them, is that they are javascript functions which are imported and injected into the html templates for other views or components -- and as javascript functions, your IDE can rename them across the codebase, and find-all-references, and you get full typescript typings for their props (whereas html-based web components do not afford you the same luxuries).
views accept js parameters called props
.
export const MyQuartz = quartz(use => (start: number) => {
const count = use.signal(start)
const increment = () => count.value++
return html`
<span>${count}</span>
<button @click=${increment}>increment</button>
`
})
const styles = css`span {color: yellow}`
export const MyObsidian = obsidian({styles}, use => (start: number) => {
const count = use.signal(start)
const increment = () => count.value++
return html`
<span>${count}</span>
<button @click=${increment}>increment</button>
`
})
auto_exportparts
is enabled by default:
part
attribute, then it will automatically re-export all internal parts, using the part as a prefix::part(search-input-icon)
html`
<aside>
${MyQuartz(123)}
</aside>
`
html`
<aside>
${MyObsidian([123])}
</aside>
`
html`
<aside>
${MyObsidian([123], {
auto_exportparts: true,
attrs: {
part: "cool",
"data-whatever": true,
},
content: html`
<p>slotted content</p>
`,
})}
</aside>
`
<obsidian-view>
componentuse
hooksconst [count, setCount] = use.state(0)
const increment = () => setCount(count + 1)
const count = use.signal(0)
const increment = () => count.value++
you can directly inject the whole signal into html
html`<span>${count}</span>`
const count = use.op()
count.run(async() => fetchCount("/count"))
const state = use.flatstate({count: 0})
const increment = () => state.count++
use.setup(() => {
const interval = setInterval(increment, 1000)
return () => clearInterval(interval)
})
const random_number = use.prepare(() => Math.random())
await use.context.flat.wait
by default, context has theme
, tower
, and flat
, but you specify your own context in prepare_frontend
, so you can put any app-level state in there that you might wantuse
accessuse.element.querySelector("p")
use.shadow.querySelector("slot")
const attrs = use.attrs({
start: Number,
label: String,
["data-active"]: Boolean,
})
set them like normal js properties
attrs.start = 123
attrs.label = "hello"
attrs["data-active"] = true
get them like normal js properties
console.log(attrs.start) // 123
console.log(attrs.label) // "hello"
console.log(attrs["data-active"]) // true
components rerender when any attributes change from outsideGoldElement
is a shadow-dom component base classSilverElement
is a light-dom component base classmixins
Attributes.base(this as BaseElement, {label: String})
to create attribute accessorsprepare_frontend
vs deferred_frontend
prepare_frontend
"bakes" your app context into the component and view functions at import-time, "before" your components and views are defined. this makes your developer experience simple and pleasant.deferred_frontend
is an alternative designed to solve this problem by deferring the passing of context to each individual component and view.provide
function which makes it easy to pass context to a group of views for that purpose.no docs for this yet
flatstate help you create state objects and react when properties change.
flatstate is inspired by mobx and snapstate, but designed to be super simple: flatstate only works on flat state objects, only the direct properties of state objects are tracked for reactivity.
import {Flat} from "@benev/slate"
const flat = new Flat()
// what happens in this flat, stays in this flat.
// you probably only want one for your whole app.
const state = flat.state({count: 0})
flat.reaction(() => console.log(state.count))
//> 0
state.count++
//> 1
const flat = new Flat()
const state = flat.state({amount: 100})
state.amount = 101
console.log(state.amount) //> 100 (old value)
await flat.wait
console.log(state.amount) //> 101 (now it's ready)
const stop = flat.reaction(() => console.log(state.count))
stop() // end this particular reaction
// clear all reactions on this flat instance
flat.clear()
flat.reaction(() => console.log(state.count))
flat.reaction(
() => ({count: state.count}),
({count}) => console.log(count),
)
const c = Flat.collectivize(state)
flat.reaction(
c(({count}) => ({count})),
({count}) => console.log(count)
)
flat.deepReaction(() => console.log(state.count))
.auto
and .manual
reactions
discovery
and debounce
(you can turn off the debouncer)const flat1 = new Flat()
const flat2 = new Flat()
const state = flat.state({count: 0})
const rstate = Flat.readonly(state)
state.count = 1
await flat.wait
console.log(rstate.count) //> 1
rstate.count = 2 // !! ReadonlyError !!
import {apply} from "@benev/slate"
const MyElement2 = mixin.flat(flat)(MyElement)
// can also be a class decorator
const elements2 = apply.flat(flat)(elements)
// bad
register_to_dom(
apply.signals(signals)(
apply.flat(flat)(
apply.css(theme)(
requirement.provide(context)(elements)
)
)
)
)
import {Pipe} from "@benev/slate"
// good
Pipe.with(elements)
.to(requirement.provide(context))
.to(apply.css(theme))
.to(apply.flat(flat))
.to(apply.signals(signals))
.to(register_to_dom)
utility for ui loading/error/ready states.
useful for implementing async operations that involve loading indicators.
import {Op} from "@benev/slate"
Op.loading()
//= {mode: "loading"}
Op.error("a fail occurred")
//= {mode: "error", reason: "a fail occurred"}
Op.ready(123)
//= {mode: "ready", payload: 123}
let my_op = Op.loading()
await Op.run(op => my_op = op, async() => {
await nap(1000)
return 123
})
const count = use.op()
count.run(async() => {
await sleep(1000)
return 123
})
// type for op in any mode
// v
function example(op: Op.Any<number>) {
// branching based on the op's mode
Op.select(op, {
loading: () => console.log("op is loading"),
error: reason => console.log("op is error", reason),
ready: payload => console.log("op is ready", payload)
})
const payload = Op.payload(op)
// if the mode=ready, return the payload
// otherwise, return undefined
}
FAQs
frontend web stuff
The npm package @benev/slate receives a total of 123 weekly downloads. As such, @benev/slate popularity was classified as not popular.
We found that @benev/slate demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.