import React from 'react'; import { ContentPage } from '../../components/ContentPage'; import { InfoPanel } from '../../components/InfoPanel'; import { ApiSection } from '../../types'; const observerApi: ApiSection[] = [ { title: 'Chemical.Observer', description: 'Creates an observer that reacts to changes in a stateful source (Value, Table, Map, or Computed). It allows you to register callbacks that fire when the source changes.', entries: [ { signature: 'Chemical.Observer(sourceObject: Stateful): Observer', description: 'Constructs a new Observer for the given stateful source.', parameters: [ { name: 'sourceObject', type: 'Stateful', description: 'The Value, Table, Map, or Computed object to observe.' }, ], returns: { type: 'Observer', description: 'A new Observer object.' }, example: ` local Chemical = require(game.ReplicatedStorage.Chemical) local Value = Chemical.Value local Map = Chemical.Map local Observer = Chemical.Observer local name = Value("Alice") local nameObserver = Observer(name) local settings = Map({ theme = "dark" }) local settingsObserver = Observer(settings) `, }, ], }, { title: 'Observer Methods', entries: [ { signature: 'observer:onChange(callback: (newValue: T, oldValue: T) -> ()): Connection', description: 'Registers a callback function that will be invoked when the observed source value changes. The callback receives the new and old values.', parameters: [ { name: 'callback', type: '(newValue: T, oldValue: T) -> ()', description: 'The function to call on change.' }, ], returns: { type: 'Connection', description: 'A connection object with a `:disconnect()` method to stop listening.' }, example: ` local Chemical = require(game.ReplicatedStorage.Chemical) local Value = Chemical.Value local Observer = Chemical.Observer local age = Value(25) local ageObs = Observer(age) local connection = ageObs:onChange(function(newAge, oldAge) print("Age changed from " .. oldAge .. " to " .. newAge) end) age:set(26) -- Output: Age changed from 25 to 26 (callback fires immediately) connection:disconnect() -- Stop observing age:set(27) -- Callback will not fire `, }, { signature: 'observer:onKVChange(callback: (path: (string|number)[], newValue: any, oldValue: any) -> ()): Connection', description: 'If the observed source is a Table or Map, this registers a callback for fine-grained changes to its keys/values. The callback receives the path (array of keys/indices) to the changed element, the new value at that path, and the old value. This is useful for deep comparison of table structures.', parameters: [ { name: 'callback', type: '(path, newValue, oldValue) -> ()', description: 'The function to call on key-value change.' }, ], returns: { type: 'Connection', description: 'A connection object with a `:disconnect()` method.' }, example: ` local Chemical = require(game.ReplicatedStorage.Chemical) local Map = Chemical.Map local Observer = Chemical.Observer local userProfile = Map({ name = "Bob", details = { "email", "phone" } -- Plain table for details }) local profileObs = Observer(userProfile) profileObs:onKVChange(function(path, newValue, oldValue) print("Profile changed at path:", table.concat(path, "."), "from", oldValue, "to", newValue) end) userProfile:key("name", "Robert") -- Output: Profile changed at path: name from Bob to Robert (callback fires immediately) -- To observe changes within the 'details' plain table, you'd typically -- replace the 'details' table itself or use a Chemical.Table if 'details' needed its own reactivity. local newDetails = table.clone(userProfile:get().details) newDetails[1] = "new_email@example.com" userProfile:key("details", newDetails) -- Output: Profile changed at path: details from table: XXX to table: YYY (actual addresses will vary) -- And then another event for the specific change if the new table is compared deeply: -- Output: Profile changed at path: details.1 from email to new_email@example.com `, notes: "This method is only effective if the source object's value is a table/map and it's marked for deep comparison (Chemical handles this for Table/Map types)." }, { signature: 'observer:destroy()', description: 'Destroys the Observer object, disconnecting all its registered callbacks and cleaning up resources.', example: ` local Chemical = require(game.ReplicatedStorage.Chemical) local Value = Chemical.Value local Observer = Chemical.Observer local status = Value("active") local statusObs = Observer(status) statusObs:onChange(function() print("Status updated") end) -- ... later statusObs:destroy() status:set("inactive") -- The onChange callback will no longer fire `, }, ], }, ]; export const ObserverPage: React.FC = () => { return (

Callbacks registered with an Observer (e.g., observer:onChange(), observer:onKVChange()) are executed immediately and synchronously when the observed source's state is updated (e.g., via :set() for a Value, or through relevant methods for Table/Map).

); };