refactor(ts-migration): Phase 11 batch 6 — agent and skill components
The fifteen files under `src/components/agents/` (including `skills/`)
and `src/components/skills/`. 15/15 erase byte-identically; bundle hash
unchanged.
Renaming raised 43 errors and 29 of them came from one thing: these
files carry 24 `/** @param {any} props */` annotations, one per
component, and JSDoc stops applying at the extension boundary. Without
them TypeScript infers every destructured prop as required, so a call
site passing seven of nine props is an error — which is how a file that
declared its props `any` ended up with fourteen complaints about missing
`className`. Restoring the author's own declaration as `: any` is not
blanket typing; it is the annotation that was already there, in the only
form that still works.
`Workspace` in `AgentCanvas` was the one component in that file its
author left without the hatch. It now matches its siblings.
The rest were five separate things:
- `React.isValidElement(children)` no longer narrows enough to read
`children.props.id`: React 19 types `ReactElement`'s props as
`unknown`. `isValidElement<any>` says what the `cloneElement` call
beneath it has always assumed. The migration plan predicted this
site by name.
- `useSkillSections(page, placement)` is called with one argument by
`UiEditingProvider`, which its doc comment explicitly permits —
"called with no placement it returns every section on the page". The
parameter simply lacked its optional marker. The marker erases, so
the emitted signature is unchanged.
- `new Date(b.at) - new Date(a.at)` is valueOf coercion, which
JavaScript performs and TypeScript refuses to describe. Cast rather
than rewritten to `.getTime()`: that would change the emitted code,
and this comparison orders the list.
- `Object.values<any>` on a tally, the same inference gap as earlier
batches, which also fixed a `ReactNode` complaint downstream of it.
All fifteen are linted under their new extensions, checked by name.
Measured against `446df7b`:
typecheck 6 errors, down from 9; no new error anywhere
lint exit 0, 0 errors, 289 warnings, 15/15 linted by name
npm test 1684/1691, the same 7 failures verbatim
build exit 0, identical bundle hash 74d17e2d…
type erasure 72/72 byte-identical across Phase 11 so far
No baseline artifact touched.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HBG1wnuRfJKCstGB8Fekr8
This commit is contained in:
@@ -44,7 +44,7 @@ import OwliverAvatar from '@/components/krow/OwliverAvatar';
|
|||||||
* holds a ~380px track on the right of every Admin page, so below `xl` the
|
* holds a ~380px track on the right of every Admin page, so below `xl` the
|
||||||
* remaining width belongs to the editor and the rail becomes a strip above it.
|
* remaining width belongs to the editor and the rail becomes a strip above it.
|
||||||
*/
|
*/
|
||||||
export function Workspace({ rail, children, className }) {
|
export function Workspace({ rail, children, className }: any) {
|
||||||
return (
|
return (
|
||||||
<div className={cn('w-full rounded-2xl border border-border bg-surface shadow-xs overflow-hidden', className)}>
|
<div className={cn('w-full rounded-2xl border border-border bg-surface shadow-xs overflow-hidden', className)}>
|
||||||
<div className="border-b border-border/80 bg-surface-subtle/40 px-4 py-3 sm:px-6">
|
<div className="border-b border-border/80 bg-surface-subtle/40 px-4 py-3 sm:px-6">
|
||||||
@@ -64,8 +64,7 @@ export function Workspace({ rail, children, className }) {
|
|||||||
* height without measuring it in JavaScript. Content stays mounted, which is
|
* height without measuring it in JavaScript. Content stays mounted, which is
|
||||||
* what keeps a section addressable by the rail while it is closed.
|
* what keeps a section addressable by the rail while it is closed.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
export function Collapse({ open, children, className }: any) {
|
||||||
export function Collapse({ open, children, className }) {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -100,8 +99,7 @@ export function Collapse({ open, children, className }) {
|
|||||||
* Provides clear section navigation and leaf anchor shortcuts across the
|
* Provides clear section navigation and leaf anchor shortcuts across the
|
||||||
* configuration workspace.
|
* configuration workspace.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
export function Rail({ sections, activeId, onSelect }: any) {
|
||||||
export function Rail({ sections, activeId, onSelect }) {
|
|
||||||
const activeSection = sections.find((s) => s.id === activeId);
|
const activeSection = sections.find((s) => s.id === activeId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -181,11 +179,10 @@ export function Rail({ sections, activeId, onSelect }) {
|
|||||||
/**
|
/**
|
||||||
* One section of the document.
|
* One section of the document.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
|
||||||
export function DocSection({
|
export function DocSection({
|
||||||
id, icon: Icon, title, description, meta, open, onToggle, emphasis = false, last = false,
|
id, icon: Icon, title, description, meta, open, onToggle, emphasis = false, last = false,
|
||||||
children,
|
children,
|
||||||
}) {
|
}: any) {
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id={id}
|
id={id}
|
||||||
@@ -257,8 +254,7 @@ export function DocSection({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A labelled field in the document body. */
|
/** A labelled field in the document body. */
|
||||||
/** @param {any} props */
|
export function DocField({ id, label, hint, children, className }: any) {
|
||||||
export function DocField({ id, label, hint, children, className }) {
|
|
||||||
const reactId = React.useId();
|
const reactId = React.useId();
|
||||||
const controlId = id ? `${id}-control` : reactId;
|
const controlId = id ? `${id}-control` : reactId;
|
||||||
|
|
||||||
@@ -270,7 +266,7 @@ export function DocField({ id, label, hint, children, className }) {
|
|||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</label>
|
</label>
|
||||||
{React.isValidElement(children)
|
{React.isValidElement<any>(children)
|
||||||
? React.cloneElement(children, { id: children.props.id || controlId })
|
? React.cloneElement(children, { id: children.props.id || controlId })
|
||||||
: children}
|
: children}
|
||||||
{hint && <p className="text-caption leading-relaxed text-ink-4">{hint}</p>}
|
{hint && <p className="text-caption leading-relaxed text-ink-4">{hint}</p>}
|
||||||
@@ -284,8 +280,7 @@ export function DocField({ id, label, hint, children, className }) {
|
|||||||
* One notch quieter than a section title and one louder than a row, which is
|
* One notch quieter than a section title and one louder than a row, which is
|
||||||
* exactly the level of the thing it names.
|
* exactly the level of the thing it names.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
export function GroupHead({ id, icon: Icon, title, count, action, className }: any) {
|
||||||
export function GroupHead({ id, icon: Icon, title, count, action, className }) {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={id}
|
id={id}
|
||||||
@@ -310,8 +305,7 @@ export function GroupHead({ id, icon: Icon, title, count, action, className }) {
|
|||||||
* competing with the section that holds them; as rows they read as a list,
|
* competing with the section that holds them; as rows they read as a list,
|
||||||
* which is what they are.
|
* which is what they are.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
export function ItemRow({ icon: Icon, title, detail, warning, onRemove, removeLabel }: any) {
|
||||||
export function ItemRow({ icon: Icon, title, detail, warning, onRemove, removeLabel }) {
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={`group/item -mx-2 flex items-start gap-2.5 rounded-lg px-2 py-2
|
className={`group/item -mx-2 flex items-start gap-2.5 rounded-lg px-2 py-2
|
||||||
@@ -352,10 +346,9 @@ export function ItemRow({ icon: Icon, title, detail, warning, onRemove, removeLa
|
|||||||
* a switch in a button makes one press mean two things. A setting that needs
|
* a switch in a button makes one press mean two things. A setting that needs
|
||||||
* space gets a chevron and opens underneath.
|
* space gets a chevron and opens underneath.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
|
||||||
export function SettingRow({
|
export function SettingRow({
|
||||||
id, icon: Icon, title, value, description, control, children, open, onToggle, last = false,
|
id, icon: Icon, title, value, description, control, children, open, onToggle, last = false,
|
||||||
}) {
|
}: any) {
|
||||||
const expandable = Boolean(children);
|
const expandable = Boolean(children);
|
||||||
|
|
||||||
const body = (
|
const body = (
|
||||||
@@ -412,8 +405,7 @@ export function SettingRow({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A page an agent covers, or one it could. */
|
/** A page an agent covers, or one it could. */
|
||||||
/** @param {any} props */
|
export function ScopeChip({ active, children, ...props }: any) {
|
||||||
export function ScopeChip({ active, children, ...props }) {
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -443,8 +435,7 @@ export function ScopeChip({ active, children, ...props }) {
|
|||||||
/* ── Identity ────────────────────────────────────────────────────────────── */
|
/* ── Identity ────────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
/** The icons an agent may wear, as a picker. */
|
/** The icons an agent may wear, as a picker. */
|
||||||
/** @param {any} props */
|
export function IconPicker({ icons, value, onChange }: any) {
|
||||||
export function IconPicker({ icons, value, onChange }) {
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-5 gap-1.5">
|
<div className="grid grid-cols-5 gap-1.5">
|
||||||
{icons.map((icon) => {
|
{icons.map((icon) => {
|
||||||
@@ -486,8 +477,7 @@ export function IconPicker({ icons, value, onChange }) {
|
|||||||
* same three things the switcher renders — icon, name, description — and
|
* same three things the switcher renders — icon, name, description — and
|
||||||
* nothing it does not.
|
* nothing it does not.
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
export function AgentPreview({ name, description, icon }: any) {
|
||||||
export function AgentPreview({ name, description, icon }) {
|
|
||||||
const Icon = agentIconFor(icon);
|
const Icon = agentIconFor(icon);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -94,7 +94,6 @@ function useActiveSection(ids) {
|
|||||||
return [active, setActive];
|
return [active, setActive];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function AgentConfigure({
|
export function AgentConfigure({
|
||||||
fields, agents, customSkills = [], onChange, onOpenSkills, scopeLocked = false,
|
fields, agents, customSkills = [], onChange, onOpenSkills, scopeLocked = false,
|
||||||
/* Attaching and detaching a skill goes through the caller's existing write
|
/* Attaching and detaching a skill goes through the caller's existing write
|
||||||
@@ -107,7 +106,7 @@ export function AgentConfigure({
|
|||||||
/* The tools this deployment registers, from GET /api/v1/tools. Passed in
|
/* The tools this deployment registers, from GET /api/v1/tools. Passed in
|
||||||
rather than fetched here so this component stays a form over `fields`. */
|
rather than fetched here so this component stays a form over `fields`. */
|
||||||
toolCatalogue = [],
|
toolCatalogue = [],
|
||||||
}) {
|
}: any) {
|
||||||
/* Sections are open by default: this is a document, and one that greets its
|
/* Sections are open by default: this is a document, and one that greets its
|
||||||
author with four closed headers hides the thing they came to write. Closing
|
author with four closed headers hides the thing they came to write. Closing
|
||||||
is for focus, not for the initial reading. */
|
is for focus, not for the initial reading. */
|
||||||
@@ -22,8 +22,7 @@ import { cn } from '@/lib/utils';
|
|||||||
* Real-time usage analytics computed directly from the local telemetry log.
|
* Real-time usage analytics computed directly from the local telemetry log.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @param {any} props */
|
function MetricCard({ icon: Icon, label, value, detail, highlight }: any) {
|
||||||
function MetricCard({ icon: Icon, label, value, detail, highlight }) {
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-2xl border border-border bg-surface p-5 shadow-xs space-y-2">
|
<div className="rounded-2xl border border-border bg-surface p-5 shadow-xs space-y-2">
|
||||||
<div className="flex items-center justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
@@ -45,8 +44,7 @@ function MetricCard({ icon: Icon, label, value, detail, highlight }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
export function AgentInsightsPanel({ agentId, agentName }: any) {
|
||||||
export function AgentInsightsPanel({ agentId, agentName }) {
|
|
||||||
const preferences = usePreferences();
|
const preferences = usePreferences();
|
||||||
|
|
||||||
const [records] = React.useState(() => readHistory());
|
const [records] = React.useState(() => readHistory());
|
||||||
@@ -46,8 +46,7 @@ const CLASSIFICATION_COPY = {
|
|||||||
combined: 'Requires both structured records and knowledge retrieval.',
|
combined: 'Requires both structured records and knowledge retrieval.',
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @param {any} props */
|
export function AgentTestPanel({ fields, dirty, customSkills = [], onRunLive }: any) {
|
||||||
export function AgentTestPanel({ fields, dirty, customSkills = [], onRunLive }) {
|
|
||||||
const [contextId, setContextId] = React.useState(
|
const [contextId, setContextId] = React.useState(
|
||||||
() => CONTEXT_OPTIONS.find((o) => fields.pages.includes(pageKeyForContext(o.contextId)))?.contextId
|
() => CONTEXT_OPTIONS.find((o) => fields.pages.includes(pageKeyForContext(o.contextId)))?.contextId
|
||||||
|| CONTEXT_OPTIONS[0].contextId
|
|| CONTEXT_OPTIONS[0].contextId
|
||||||
@@ -43,7 +43,6 @@ import { SkillDetails } from './SkillDetails';
|
|||||||
const OWLIVER = 'owliver';
|
const OWLIVER = 'owliver';
|
||||||
const BOARD = 'board';
|
const BOARD = 'board';
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function AgentSkillWorkspace({
|
export function AgentSkillWorkspace({
|
||||||
fields,
|
fields,
|
||||||
customSkills = [],
|
customSkills = [],
|
||||||
@@ -55,7 +54,7 @@ export function AgentSkillWorkspace({
|
|||||||
busy = false,
|
busy = false,
|
||||||
pendingId = null,
|
pendingId = null,
|
||||||
dirty = false,
|
dirty = false,
|
||||||
}) {
|
}: any) {
|
||||||
const [kind, setKind] = React.useState(OWLIVER);
|
const [kind, setKind] = React.useState(OWLIVER);
|
||||||
const [query, setQuery] = React.useState('');
|
const [query, setQuery] = React.useState('');
|
||||||
const [boardQuery, setBoardQuery] = React.useState('');
|
const [boardQuery, setBoardQuery] = React.useState('');
|
||||||
@@ -174,7 +174,6 @@ function StaticLeaf({ icon: Icon, label, detail = null }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function AgentTree({
|
export function AgentTree({
|
||||||
agentName,
|
agentName,
|
||||||
agentIcon,
|
agentIcon,
|
||||||
@@ -191,7 +190,7 @@ export function AgentTree({
|
|||||||
onToggleBranch,
|
onToggleBranch,
|
||||||
busy = false,
|
busy = false,
|
||||||
className,
|
className,
|
||||||
}) {
|
}: any) {
|
||||||
const Glyph = agentIconFor(agentIcon);
|
const Glyph = agentIconFor(agentIcon);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -159,11 +159,10 @@ function BoardCard({ entry, enabled, onToggle, onSurfaces, busy, attached = fals
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function BoardSkillList({
|
export function BoardSkillList({
|
||||||
entries, agentPages = [], disabledIds, onToggle, busy = false, query, onQueryChange, total,
|
entries, agentPages = [], disabledIds, onToggle, busy = false, query, onQueryChange, total,
|
||||||
attachedIds = null, onAttach = null,
|
attachedIds = null, onAttach = null,
|
||||||
}) {
|
}: any) {
|
||||||
const searchId = React.useId();
|
const searchId = React.useId();
|
||||||
const onSurfaces = React.useMemo(() => new Set(agentPages), [agentPages]);
|
const onSurfaces = React.useMemo(() => new Set(agentPages), [agentPages]);
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ import { glyphForGroup } from './glyphs';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {any} */
|
/** @type {any} */
|
||||||
export const SkillCard = React.memo(/** @param {any} props */ ({
|
export const SkillCard = React.memo(({
|
||||||
entry, enabled, onOpen, onAddAgent, onTest, canTest = false, busy = false, isPending = false,
|
entry, enabled, onOpen, onAddAgent, onTest, canTest = false, busy = false, isPending = false,
|
||||||
}) => {
|
}: any) => {
|
||||||
const Glyph = glyphForGroup(entry.group);
|
const Glyph = glyphForGroup(entry.group);
|
||||||
const samplePrompt = entry.suggestions?.[0]?.label;
|
const samplePrompt = entry.suggestions?.[0]?.label;
|
||||||
|
|
||||||
@@ -23,8 +23,7 @@ import { SkillCard } from './SkillCard';
|
|||||||
* has, at every width, with no media query to get wrong.
|
* has, at every width, with no media query to get wrong.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @param {any} props */
|
function CategoryFilter({ groups, value, onChange, total }: any) {
|
||||||
function CategoryFilter({ groups, value, onChange, total }) {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role="group"
|
role="group"
|
||||||
@@ -60,7 +59,6 @@ function CategoryFilter({ groups, value, onChange, total }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function SkillCatalog({
|
export function SkillCatalog({
|
||||||
entries,
|
entries,
|
||||||
groups,
|
groups,
|
||||||
@@ -76,7 +74,7 @@ export function SkillCatalog({
|
|||||||
testableIds,
|
testableIds,
|
||||||
busy = false,
|
busy = false,
|
||||||
pendingId = null,
|
pendingId = null,
|
||||||
}) {
|
}: any) {
|
||||||
const searchId = React.useId();
|
const searchId = React.useId();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -82,11 +82,10 @@ function TestState({ test, entryId }) {
|
|||||||
* button needs the same `surface` this renders, and two copies of that would be
|
* button needs the same `surface` this renders, and two copies of that would be
|
||||||
* two answers to "what am I about to enable".
|
* two answers to "what am I about to enable".
|
||||||
*/
|
*/
|
||||||
/** @param {any} props */
|
|
||||||
export function CapabilityBrief({
|
export function CapabilityBrief({
|
||||||
entry, attached, surface, onSurfaceChange, question, onQuestionChange,
|
entry, attached, surface, onSurfaceChange, question, onQuestionChange,
|
||||||
canTest, target, onTest, test, busy = false, showTest = true,
|
canTest, target, onTest, test, busy = false, showTest = true,
|
||||||
}) {
|
}: any) {
|
||||||
const { shapes, described } = entry.capabilities;
|
const { shapes, described } = entry.capabilities;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -252,11 +251,10 @@ export function CapabilityBrief({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function SkillDetails({
|
export function SkillDetails({
|
||||||
entry, open, onOpenChange, isEnabledOn, onToggle, busy = false,
|
entry, open, onOpenChange, isEnabledOn, onToggle, busy = false,
|
||||||
fields = null, onRunTest = null, test = null,
|
fields = null, onRunTest = null, test = null,
|
||||||
}) {
|
}: any) {
|
||||||
/**
|
/**
|
||||||
* The surface this would run on.
|
* The surface this would run on.
|
||||||
*
|
*
|
||||||
@@ -45,8 +45,7 @@ const OPTIONS = [
|
|||||||
export const supportedSurfaces = (type) =>
|
export const supportedSurfaces = (type) =>
|
||||||
OPTIONS.filter((o) => o.supported(type)).map((o) => o.id);
|
OPTIONS.filter((o) => o.supported(type)).map((o) => o.id);
|
||||||
|
|
||||||
/** @param {any} props */
|
export function SurfaceSelect({ type, value, onChange, name }: any) {
|
||||||
export function SurfaceSelect({ type, value, onChange, name }) {
|
|
||||||
return (
|
return (
|
||||||
<div role="radiogroup" aria-label={`Run ${name} as`} className="space-y-1.5">
|
<div role="radiogroup" aria-label={`Run ${name} as`} className="space-y-1.5">
|
||||||
{OPTIONS.map((option) => {
|
{OPTIONS.map((option) => {
|
||||||
@@ -133,7 +133,7 @@ function ListSection({ data }) {
|
|||||||
function TimelineSection({ data }) {
|
function TimelineSection({ data }) {
|
||||||
const items = [...(data.items || [])]
|
const items = [...(data.items || [])]
|
||||||
.filter((item) => item.at)
|
.filter((item) => item.at)
|
||||||
.sort((a, b) => new Date(b.at) - new Date(a.at));
|
.sort((a, b) => (new Date(b.at) as any) - (new Date(a.at) as any));
|
||||||
if (data.empty || !items.length) return <EmptyNote>{data.emptyNote}</EmptyNote>;
|
if (data.empty || !items.length) return <EmptyNote>{data.emptyNote}</EmptyNote>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -308,7 +308,7 @@ function WeightsSection({ data, section, onApply, compact = false }) {
|
|||||||
if (data?.empty || !rows.length) return <EmptyNote>{data?.emptyNote}</EmptyNote>;
|
if (data?.empty || !rows.length) return <EmptyNote>{data?.emptyNote}</EmptyNote>;
|
||||||
|
|
||||||
const current = draft || Object.fromEntries(rows.map((r) => [r.id, Number(r.value) || 0]));
|
const current = draft || Object.fromEntries(rows.map((r) => [r.id, Number(r.value) || 0]));
|
||||||
const total = Object.values(current).reduce((a, b) => a + b, 0);
|
const total = Object.values<any>(current).reduce((a, b) => a + b, 0);
|
||||||
const balanced = total === 100;
|
const balanced = total === 100;
|
||||||
const dirty = draft !== null && rows.some((r) => (Number(r.value) || 0) !== current[r.id]);
|
const dirty = draft !== null && rows.some((r) => (Number(r.value) || 0) !== current[r.id]);
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ import { agentPermitsSkill } from '@/lib/agents/runtime';
|
|||||||
* from one resolution, or the two would disagree about what a page carries.
|
* from one resolution, or the two would disagree about what a page carries.
|
||||||
* Called with no placement it returns every section on the page.
|
* Called with no placement it returns every section on the page.
|
||||||
*/
|
*/
|
||||||
export function useSkillSections(page, placement) {
|
export function useSkillSections(page, placement?) {
|
||||||
const preferences = usePreferences();
|
const preferences = usePreferences();
|
||||||
/**
|
/**
|
||||||
* Who is answering here.
|
* Who is answering here.
|
||||||
@@ -217,7 +217,6 @@ function SkillSection({ skill, section, context }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {any} props */
|
|
||||||
export function SkillSurface({
|
export function SkillSurface({
|
||||||
page = '',
|
page = '',
|
||||||
placement = '',
|
placement = '',
|
||||||
@@ -231,7 +230,7 @@ export function SkillSurface({
|
|||||||
_customSources = [],
|
_customSources = [],
|
||||||
_email = '',
|
_email = '',
|
||||||
_onOpenTraining = null,
|
_onOpenTraining = null,
|
||||||
}) {
|
}: any) {
|
||||||
const sections = useSkillSections(page, placement);
|
const sections = useSkillSections(page, placement);
|
||||||
const resolved = useSkillDataContext(context);
|
const resolved = useSkillDataContext(context);
|
||||||
|
|
||||||
Reference in New Issue
Block a user