ebox-playground/examples/interaction-reference.el
Kinneyzhang 6cd5a67a35 feat: add sizing and interactive text reference examples
Load same-basename Elisp companions through the generic preview runner. Demonstrate size semantics and native help, pointer, hover and keymap behavior with isolated example state.

Update Flex and Grid examples and extend reusable comparison and interaction evaluators with publication, allocation and fresh-render parity checks.

Validation: make check passed, including all 72 Playground tests.
2026-09-09 22:25:28 +08:00

152 lines
6.3 KiB
EmacsLisp

;;; interaction-reference.el --- State and actions for the interaction lab -*- lexical-binding: t; -*-
;;; Commentary:
;; Loaded by the generic playground runner before interaction-reference.ebox.
;; Each DSL evaluation creates its own state. Ebox supplies command/keymap
;; construction, mouse-buffer targeting, and named-region updates.
;;; Code:
(require 'ebox)
(require 'cl-lib)
(require 'seq)
(require 'subr-x)
(cl-defstruct (interaction-demo
(:constructor interaction-demo--make))
"Application state belonging to one interaction-lab preview."
(count 0) (step 1) (enabled t) warm events (serial 0) keymap subtract-keymap)
(defun interaction-demo-create ()
"Create independent state and bindings for a new preview."
(let ((demo (interaction-demo--make)))
(setf (interaction-demo-keymap demo)
(interaction-demo--step-map demo)
(interaction-demo-subtract-keymap demo)
(interaction-demo--step-map demo t))
demo))
(defun interaction-demo-description (demo &optional subtract)
"Return DEMO's current action hint, describing subtraction when SUBTRACT."
(format "Live help: count = %d; this action %s %d. RET / SPC / click."
(interaction-demo-count demo) (if subtract "subtracts" "adds")
(interaction-demo-step demo)))
(defun interaction-demo--record (demo description)
"Record DEMO's action DESCRIPTION and refresh its four-line event log."
(push (format "%02d %s" (cl-incf (interaction-demo-serial demo))
description)
(interaction-demo-events demo))
(setf (interaction-demo-events demo)
(seq-take (interaction-demo-events demo) 4))
(let ((events (interaction-demo-events demo)))
(ebox-region-update
"event-log" :content
(string-join (append events (make-list (- 4 (length events)) "")) "\n"))))
(defun interaction-demo--show-count (demo)
"Refresh the displayed count for DEMO."
(ebox-region-update "count" :content
(format "COUNT %02d" (interaction-demo-count demo))))
(defun interaction-demo--add (demo amount)
"Add AMOUNT to DEMO's count and record the action."
(cl-incf (interaction-demo-count demo) amount)
(interaction-demo--show-count demo)
(interaction-demo--record
demo (format "%+d → count %d" amount (interaction-demo-count demo))))
(defun interaction-demo-hover (demo)
"Return DEMO's chosen hover palette using ordinary Ebox declarations."
(if (interaction-demo-warm demo)
'(:background-color "#F6D6AB" :color "#683D16"
:text-decoration-line underline)
'(:background-color "#BCDDE5" :color "#123E4B"
:text-decoration-line underline)))
(defun interaction-demo--step-map (demo &optional subtract)
"Create DEMO's captured step map, with SUBTRACT choosing negative activation."
(let ((amount (interaction-demo-step demo)))
(ebox-keymap-create
:activate (lambda ()
(interaction-demo--add demo (if subtract (- amount) amount)))
:bindings
(list (cons "+" (lambda () (interaction-demo--add demo amount)))
(cons "-" (lambda () (interaction-demo--add demo (- amount))))))))
(defun interaction-demo--refresh (demo)
"Publish DEMO's current action properties and binding summary."
(let ((enabled (interaction-demo-enabled demo))
(step (interaction-demo-step demo)))
(ebox-region-update
"live-action"
:help-echo (and enabled
(ebox-help-create
(apply-partially #'interaction-demo-description demo)))
:pointer (and enabled 'hand)
:hover-style (and enabled (interaction-demo-hover demo))
:keymap (and enabled (interaction-demo-keymap demo)))
(ebox-region-update
"action-label" :content
(if enabled (format "ADD %d [+] " step) "BINDING REMOVED "))
(ebox-region-update
"subtract-text"
:help-echo (and enabled
(ebox-help-create
(apply-partially #'interaction-demo-description demo t)))
:keymap (and enabled (interaction-demo-subtract-keymap demo))))
(ebox-region-update
"binding-state" :content
(format "step %d · %s · %s hover"
(interaction-demo-step demo)
(if (interaction-demo-enabled demo)
"four properties attached" "four properties nil")
(if (interaction-demo-warm demo) "warm" "cool"))))
(defun interaction-demo-action (demo action)
"Return a native activation keymap for DEMO's named ACTION."
(ebox-keymap-create
:activate
(lambda ()
(pcase action
('step
(setf (interaction-demo-step demo)
(if (= (interaction-demo-step demo) 1) 5 1)
(interaction-demo-keymap demo)
(interaction-demo--step-map demo)
(interaction-demo-subtract-keymap demo)
(interaction-demo--step-map demo t))
(interaction-demo--refresh demo)
(interaction-demo--record
demo (format "Replaced keymap: step %d" (interaction-demo-step demo))))
('binding
(setf (interaction-demo-enabled demo)
(not (interaction-demo-enabled demo)))
(interaction-demo--refresh demo)
(interaction-demo--record
demo (if (interaction-demo-enabled demo)
"Restored all four properties" "Removed all four properties")))
('palette
(setf (interaction-demo-warm demo)
(not (interaction-demo-warm demo)))
(interaction-demo--refresh demo)
(interaction-demo--record
demo (if (interaction-demo-warm demo)
"Hover → warm palette" "Hover → cool palette")))
('reset
(setf (interaction-demo-count demo) 0)
(interaction-demo--show-count demo)
(interaction-demo--record demo "Reset count"))
('group
(ebox-update-selector (current-buffer) ".demo-status"
:content "READY" :color "#287A52"
:help-echo "This status was updated with its class group.")
(interaction-demo--record demo "Updated three .demo-status regions in one batch"))
('parent (interaction-demo--record demo "PARENT surface activated"))
('child (interaction-demo--record demo "CHILD text activated"))
(_ (error "Unknown interaction-lab action: %S" action))))))
(provide 'interaction-demo-reference)
;;; interaction-reference.el ends here