mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
chore: update eslint, housekeeping
This commit is contained in:
parent
cb52ece4d3
commit
4a07297a13
14 changed files with 554 additions and 619 deletions
28
.eslintrc
28
.eslintrc
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"jsx": true,
|
||||
"useJSXTextNode": true,
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module",
|
||||
"project": [
|
||||
"./tsconfig.json",
|
||||
"./examples/ts/tsconfig.json"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"roblox-ts",
|
||||
"prettier"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:roblox-ts/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": "warn",
|
||||
"@typescript-eslint/no-explicit-any": "off"
|
||||
}
|
||||
}
|
||||
20
eslint.config.ts
Normal file
20
eslint.config.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import eslint from "@eslint/js";
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
import prettierRecommended from "eslint-plugin-prettier/recommended";
|
||||
import roblox from "eslint-plugin-roblox-ts";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default defineConfig(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
roblox.configs.tsRecommendedCompat,
|
||||
roblox.configs.recommended,
|
||||
{
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"roblox-ts/no-any": "off",
|
||||
},
|
||||
},
|
||||
globalIgnores(["out/**"]),
|
||||
prettierRecommended,
|
||||
);
|
||||
25
package.json
25
package.json
|
|
@ -9,21 +9,22 @@
|
|||
},
|
||||
"packageManager": "pnpm@10.17.1",
|
||||
"devDependencies": {
|
||||
"@rbxts-js/react": "17.1.20-ts.1",
|
||||
"@rbxts-js/react-roblox": "17.1.20-ts.1",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@rbxts/compiler-types": "3.0.0-types.0",
|
||||
"@rbxts/react": "17.3.0-alpha.1",
|
||||
"@rbxts/react-roblox": "17.3.0-alpha.1",
|
||||
"@rbxts/types": "^1.0.861",
|
||||
"@rbxts/react": "17.3.5-alpha.1",
|
||||
"@rbxts/react-roblox": "17.3.5-alpha.1",
|
||||
"@rbxts/types": "^1.0.883",
|
||||
"@rbxts/vide": "^0.5.7",
|
||||
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
||||
"@typescript-eslint/parser": "^8.35.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-prettier": "^5.5.1",
|
||||
"eslint-plugin-roblox-ts": "^0.0.36",
|
||||
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
||||
"@typescript-eslint/parser": "^8.44.1",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-roblox-ts": "^1.2.1",
|
||||
"jiti": "^2.6.0",
|
||||
"prettier": "^3.6.2",
|
||||
"roblox-ts": "^3.0.0",
|
||||
"typescript": "^5.8.3"
|
||||
"typescript": "^5.9.2",
|
||||
"typescript-eslint": "^8.44.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
packages/charm/src/index.d.ts
vendored
14
packages/charm/src/index.d.ts
vendored
|
|
@ -26,34 +26,34 @@ export function effect(callback: () => Cleanup | void): Cleanup;
|
|||
export function effectScope(callback: () => Cleanup | void, detached?: boolean): Cleanup;
|
||||
|
||||
export function listen<T>(
|
||||
callback: () => T,
|
||||
getter: () => T,
|
||||
listener: (value: T, previousValue: T | undefined, dispose: Cleanup) => void,
|
||||
): Cleanup;
|
||||
|
||||
export function subscribe<T>(callback: () => T, listener: (value: T, previousValue: T) => void): Cleanup;
|
||||
export function subscribe<T>(getter: () => T, listener: (value: T, previousValue: T) => void): Cleanup;
|
||||
|
||||
export function mapped<VI, KI, VO, KO = KI>(
|
||||
callback: () => Map<KI, VI> | ReadonlyMap<KI, VI>,
|
||||
getter: () => Map<KI, VI> | ReadonlyMap<KI, VI>,
|
||||
mapper: (value: VI, key: KI) => LuaTuple<[VO, KO]> | VO,
|
||||
): () => ReadonlyMap<KO, VO>;
|
||||
// Overload for arrays
|
||||
export function mapped<VI, VO, K extends Key = number>(
|
||||
callback: () => readonly VI[],
|
||||
getter: () => readonly VI[],
|
||||
mapper: (value: VI, key: number) => LuaTuple<[VO, K]> | VO,
|
||||
): () => K extends number ? readonly VO[] : { readonly [P in K]: VO };
|
||||
// Overload for objects
|
||||
export function mapped<VI, KI extends Key, VO, KO extends Key = KI>(
|
||||
callback: () => { readonly [K in KI]: VI },
|
||||
getter: () => { readonly [K in KI]: VI },
|
||||
mapper: (value: VI, key: KI) => LuaTuple<[VO, KO]> | VO,
|
||||
): () => { readonly [K in KO]: VO };
|
||||
|
||||
export function observe<V, K = number>(
|
||||
callback: () => Map<K, V> | ReadonlyMap<K, V> | readonly V[],
|
||||
getter: () => Map<K, V> | ReadonlyMap<K, V> | readonly V[],
|
||||
observer: (value: V, key: K) => Cleanup | void,
|
||||
): Cleanup;
|
||||
// Overload for objects
|
||||
export function observe<V, K extends Key>(
|
||||
callback: () => { readonly [K in Key]: V },
|
||||
getter: () => { readonly [K in Key]: V },
|
||||
observer: (value: V, key: K) => Cleanup | void,
|
||||
): Cleanup;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ local untracked = require("./untracked")
|
|||
local computed = core.computed
|
||||
local effect = core.effect
|
||||
|
||||
local function listen<T>(selector: () -> T, listener: (state: T, previous: T?, dispose: () -> ()) -> ()): () -> ()
|
||||
local function listen<T>(getter: () -> T, listener: (state: T, previous: T?, dispose: () -> ()) -> ()): () -> ()
|
||||
local tracked = computed(function()
|
||||
return selector()
|
||||
return getter()
|
||||
end)
|
||||
|
||||
local current: T
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ local computed = core.computed
|
|||
local setCurrentSub = core.setCurrentSub
|
||||
|
||||
type Mapped =
|
||||
& (<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)) -> () -> { [KO]: VO })
|
||||
& (<K, VI, VO>(selector: () -> { [K]: VI }, mapper: (item: VI, key: K) -> VO) -> () -> { [K]: VO })
|
||||
& (<KI, VI, KO, VO>(getter: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)) -> () -> { [KO]: VO })
|
||||
& (<K, VI, VO>(getter: () -> { [K]: VI }, mapper: (item: VI, key: K) -> VO) -> () -> { [K]: VO })
|
||||
|
||||
local function mapped<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)): () -> { [KO]: VO }
|
||||
local function mapped<KI, VI, KO, VO>(getter: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)): () -> { [KO]: VO }
|
||||
local currentData: { [KI]: VI } = {}
|
||||
local keyCache: { [KI]: KO } = {}
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ local function mapped<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (ite
|
|||
return computed(function(previousOutput)
|
||||
local currentOutput: { [KO]: VO } = previousOutput or {}
|
||||
local previousData = currentData
|
||||
currentData = selector()
|
||||
currentData = getter()
|
||||
|
||||
for key in previousData do
|
||||
if currentData[key] ~= nil then
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ local onCleanup = core.onCleanup
|
|||
local startBatch = core.startBatch
|
||||
local endBatch = core.endBatch
|
||||
|
||||
local function observe<K, V>(selector: () -> { [K]: V }, observer: (item: V, key: K) -> ...(() -> ())?): () -> ()
|
||||
local function observe<K, V>(getter: () -> { [K]: V }, observer: (item: V, key: K) -> ...(() -> ())?): () -> ()
|
||||
local scopes: { [K]: () -> () } = {}
|
||||
local currentItems: { [K]: V } = {}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ local function observe<K, V>(selector: () -> { [K]: V }, observer: (item: V, key
|
|||
|
||||
local disposeEffect = effect(function()
|
||||
local previousItems = currentItems
|
||||
currentItems = selector()
|
||||
currentItems = getter()
|
||||
if currentItems ~= previousItems then
|
||||
startBatch()
|
||||
updateScopes(currentItems, previousItems)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ local untracked = require("./untracked")
|
|||
local computed = core.computed
|
||||
local effect = core.effect
|
||||
|
||||
local function subscribe<T>(selector: () -> T, listener: (state: T, lastState: T) -> ()): () -> ()
|
||||
local function subscribe<T>(getter: () -> T, listener: (state: T, lastState: T) -> ()): () -> ()
|
||||
local tracked = computed(function()
|
||||
return selector()
|
||||
return getter()
|
||||
end)
|
||||
|
||||
local current: T
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ test("tracks dependencies", function()
|
|||
assert(hook.result == 0, "should return 0")
|
||||
state(1)
|
||||
assert(hook.result == 1, "should return 1")
|
||||
|
||||
state = atom(0)
|
||||
hook.rerender()
|
||||
assert(hook.result == 0, "should return 0")
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ test("tracks dependencies", function()
|
|||
assert(hook.result:getValue() == 0, "should return 0")
|
||||
state(1)
|
||||
assert(hook.result:getValue() == 1, "should return 1")
|
||||
|
||||
state = atom(0)
|
||||
hook.rerender()
|
||||
assert(hook.result:getValue() == 0, "should return 0")
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
local Charm = require("./Charm")
|
||||
local React = require("./React")
|
||||
|
||||
local effect = Charm.effect
|
||||
local useBinding = React.useBinding
|
||||
local useEffect = React.useEffect
|
||||
local useState = React.useState
|
||||
local useMemo = React.useMemo
|
||||
|
||||
--- A hook that subscribes to changes in the given atom or selector. The
|
||||
--- component is re-rendered with the new state after an update.
|
||||
---
|
||||
--- If the `dependencies` array is provided, a new effect is created for the
|
||||
--- current `callback` when the dependencies change. Otherwise, the effect is
|
||||
--- current `getter` when the dependencies change. Otherwise, the effect is
|
||||
--- created only once, when the component is mounted.
|
||||
---
|
||||
--- @param callback The atom or selector to watch.
|
||||
--- @param dependencies An array of values used to memoize the callback.
|
||||
--- @param getter The atom or selector to watch.
|
||||
--- @param dependencies An array of values used to memoize the getter.
|
||||
--- @return The current state.
|
||||
local function useAtom<T>(callback: () -> T, dependencies: { any }?): T
|
||||
local state, setState = useState(callback)
|
||||
local function useAtom<T>(getter: () -> T, dependencies: { any }?): T
|
||||
local state, setState = React.useState(getter)
|
||||
|
||||
useEffect(function()
|
||||
return effect(function()
|
||||
setState(callback())
|
||||
React.useLayoutEffect(function()
|
||||
setState(getter())
|
||||
return Charm.effect(function()
|
||||
setState(getter())
|
||||
end)
|
||||
end, dependencies or {})
|
||||
|
||||
|
|
@ -33,19 +28,20 @@ end
|
|||
--- a binding that updates when the state changes.
|
||||
---
|
||||
--- If the `dependencies` array is provided, a new effect is created for the
|
||||
--- current `callback` when the dependencies change. Otherwise, the effect is
|
||||
--- current `getter` when the dependencies change. Otherwise, the effect is
|
||||
--- created only once, when the component is mounted.
|
||||
---
|
||||
--- @param callback The atom or selector to watch.
|
||||
--- @param dependencies An array of values used to memoize the callback.
|
||||
--- @param getter The atom or selector to watch.
|
||||
--- @param dependencies An array of values used to memoize the getter.
|
||||
--- @return A binding that stores the current state.
|
||||
local function useAtomBinding<T>(callback: () -> T, dependencies: { any }?)
|
||||
local initialState = useMemo(callback, {})
|
||||
local binding, setBinding = useBinding(initialState)
|
||||
local function useAtomBinding<T>(getter: () -> T, dependencies: { any }?)
|
||||
local initialState = React.useMemo(getter, {})
|
||||
local binding, setBinding = React.useBinding(initialState)
|
||||
|
||||
useEffect(function()
|
||||
return effect(function()
|
||||
setBinding(callback())
|
||||
React.useEffect(function()
|
||||
setBinding(getter())
|
||||
return Charm.effect(function()
|
||||
setBinding(getter())
|
||||
end)
|
||||
end, dependencies or {})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ local subscribe = Charm.subscribe
|
|||
local source = Vide.source
|
||||
local cleanup = Vide.cleanup
|
||||
|
||||
--- Subscribes to the state of an atom or selector. Returns a source that
|
||||
--- updates when the state changes.
|
||||
--- Returns a reactive source that updates when the given getter function's
|
||||
--- value changes.
|
||||
---
|
||||
--- @param callback The atom or selector to subscribe to.
|
||||
--- @param getter The atom or selector to subscribe to.
|
||||
--- @return The reactive source.
|
||||
local function useAtom<State>(callback: () -> State): () -> State
|
||||
local state = source(callback())
|
||||
cleanup(subscribe(callback, state))
|
||||
local function useAtom<State>(getter: () -> State): () -> State
|
||||
local state = source(getter())
|
||||
cleanup(subscribe(getter, state))
|
||||
return state
|
||||
end
|
||||
|
||||
|
|
|
|||
1009
pnpm-lock.yaml
generated
1009
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@
|
|||
"jsxFragmentFactory": "Roact.createFragment",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "Node",
|
||||
"ignoreDeprecations": "6.0",
|
||||
"noLib": true,
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue