# Esri Calcite 设计系统

## Esri Calcite 设计系统界面预览

从列表或示意图中选择站点，筛选审核状态，并验证一条按站点保存、直到重新加载前一直保留的备注。

## Esri Calcite 设计系统设计参考

Calcite 设计令牌 4.1.0 和当前组件 API，并与 Components 5.1.2 一并核对。令牌包和组件包的版本号彼此独立。内嵌示例是对 HTML/CSS 的原创演绎；它不会重新分发 Calcite 运行时，也不声称具备原生行为。

### 浅色主题的界面表面、文本与交互

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --calcite-color-surface-1 | #f7f7f7 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-surface-2 | #ffffff | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-surface-3 | #f2f2f2 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-surface-4 | #ebebeb | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-surface-highlight | #d6efff | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-text-1 | #141414 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-text-2 | #4a4a4a | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-text-3 | #6b6b6b | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-text-inverse | #ffffff | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-text-link | #00619b | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-border-1 | #d4d4d4 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-border-2 | #dedede | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-border-3 | #ebebeb | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-border-input | #949494 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-brand | #007ac2 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-brand-hover | #00619b | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
| --calcite-color-brand-press | #004874 | 用于说明令牌所代表角色的语义参考；选择状态和字段边框需要不同的对比度。 |
### 当前间距比例

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --calcite-space-none | 0 | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-px | 1px | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-base | 2px | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-2xs | 0.25rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-xs | 0.375rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-sm | 0.5rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-sm-plus | 0.625rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-md | 0.75rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-md-plus | 0.875rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-lg | 1rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-xl | 1.25rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-2xl | 1.5rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-3xl | 2rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
| --calcite-space-4xl | 2.75rem | 当前间距令牌系列。以 rem 为单位的步进值遵循根字号；避免与已弃用的间距别名混用。 |
### 字体与圆角比例

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --calcite-corner-radius-none | 0 | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-corner-radius-xs | 2px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-corner-radius-sm | 4px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-corner-radius-pill | 9999px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-xs | 10px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-sm | 12px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size | 14px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-md | 16px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-lg | 18px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-xl | 20px | 已发布的数值，而非从截图推测的测量结果。 |
| --calcite-font-size-2xl | 24px | 已发布的数值，而非从截图推测的测量结果。 |
### 输入组件 API

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| scale | s / m / l; default m | 有意识地调整组件比例；这与更改页面缩放不同。 |
| status | idle / valid / invalid | 通过提示消息说明字段是否有效，而不只依赖颜色。 |
| labelText | string | 当前输入组件 API 上可见的标签文本。 |
| validationMessage | string | 在控件旁说明无效输入。 |
| calciteInputInput | event | 在用户输入时读取 event.target.value。 |
| setFocus() | Promise<void> | 应用验证出错后，将焦点移入原生组件。 |
## Esri Calcite 设计系统完整指南

实用指南，介绍如何为真实界面选择、应用和评审此系统。

完整指导、实现起点和源代码链接。

## Esri Calcite 设计系统工作区与面板架构

### 让对象上下文保持可见

> 空间类任务通常至少包含两个上下文：正在检查的区域和选中的对象。此示例在原创示意图和检查器旁放置了一个简易站点列表。选择列表行或图钉时，都会设置同一个稳定的站点 ID，因此名称、状态和备注不会意外关联到不同对象。

### 将插图与真实地图区分开

此 SVG 用于说明列表与空间界面表面之间的关系。它不包含投影、坐标、图层、缩放、地理编码或路径规划功能。可见说明标明这是示意图，且不按比例绘制。生产环境中的 ArcGIS 视图需要单独集成 SDK、数据和无障碍功能；仅有 Calcite 外壳并不具备这些能力。

## Esri Calcite 设计系统语义颜色角色

### 用界面表面划分工具区域，避免使用厚重卡片

参考设计区分 surface-1 到 surface-4，并将 surface-highlight 专用于强调。示例在克制的灰白画布上使用白色检查器和浅蓝色选中行。细而中性的边框用于标示面板边界，避免给每个字段都加上浮动卡片。

### 让蓝色始终代表一致的交互含义

品牌色、悬停色和按下色构成一组逐渐加深的色阶：从 #007ac2 到 #00619b，再到 #004874。选中图钉和主要保存操作分别使用这一色系表达不同的交互角色。书面审核状态和备注验证消息即使不依赖颜色也清晰易读。

## Esri Calcite 设计系统字体与信息密度

### 保留精简的信息层级

已发布的绝对字号参考包括 12px 小号文本、14px 基础字号、16px 中号文本和 20px 超大字号。示例将 20px 工作区标题与 16px 面板标题和 14px 控件搭配使用。元数据字号更小，但选中对象不会只在元数据中标识。

### 区分回退字体与品牌字体

此独立示例使用 Arial 和系统字体回退，不包含 Esri 品牌字体，也不会将回退字体标注为 Avenir。经授权的原生集成应遵循所固定 Calcite 版本的资源和主题设置。更改字体可能会影响换行和控件宽度，因此请使用实际部署的资源集进行测试。

## Esri Calcite 设计系统间距令牌与响应式面板

### 选择当前令牌名称

此参考采用当前的 --calcite-space-* 比例，其中最小间距步进值以像素为单位，较大的间距则以 rem 为单位。实现原生主题时，请始终一致地使用这些命名角色。此示例的应用布局采用明确的 CSS 值，因此无需导入受限软件包也能运行。

### 先调整检查器布局，再压缩字段

在应用原始断点处，检查器会移动到列表和插图下方。在窄屏手机上，三个区域会改为纵向排列。文本区域保持全宽，并保留其标签、辅助说明和保存操作。这些断点是布局设计选择，并非 Calcite 令牌值。

## Esri Calcite 设计系统选择与筛选行为

### 使用单一选中标识符

列表和示意图通过 A-01、B-02 和 C-03 共享选中状态，而非依赖当前数组位置。筛选至 Checked 后，符合条件的站点会被选中，检查器也会随之更新。列表按钮和对应图钉都会公开按下状态。

### 将已保存备注与未保存草稿分开

已保存的备注存储在一个以站点 ID 为键的 Map 中。返回该站点时，备注会恢复；切换站点而不保存，则未保存的文本会被替换。辅助说明明确指出了数据的本地保留期限。如果丢失草稿会造成重大损失，生产环境中的编辑器应增加未保存更改保护。

## Esri Calcite 设计系统输入验证与恢复

### 使用 Calcite 时，请采用实际的原生输入 API

原生示例使用 labelText、value、status 和 validationMessage。calciteInputInput 事件可清除过时的错误；应用规则验证失败后，setFocus() 可将焦点返回组件。这些都是公开的 API 名称，不需要深入 shadow root 查找内部输入框。

### 不要将本地确认误认为服务端持久化

独立预览要求输入至少 10 个去除首尾空格的字符，且最多 240 个字符。确认信息会指出站点并明确说明备注保存在本地。重新加载页面会清除备注。联网版本还需要处理等待、失败、重试和冲突等状态；本地保存提示并不意味着具备这些能力。

1. 尝试保存空白备注或过短的备注，并查看错误提示。

2. 输入一条较长的备注并保存，然后选择其他站点，再返回原站点。

3. 重新加载页面，确认示例不会承诺持久化保存。

## Esri Calcite 设计系统无障碍空间信息替代方案

### 为每个图钉提供对应的列表项

每个可交互的图钉在站点列表中都有对应的文本按钮。因此，示意地图并非选择对象的唯一方式。其 SVG 带有简明描述，各控件也有自己的名称和清晰可见的焦点轮廓。真实地图所需的内容远不止复制示意图的替代文本。

### 在字段旁显示验证信息

文本区域通过 aria-describedby 同时关联辅助说明和错误信息。验证失败时，字段会获得 aria-invalid 属性和焦点；编辑后，过时的无效状态会被清除。确认信息使用状态区域。键盘用户无需操作绘制的地理图形，也可以选择站点、输入备注并保存。

## Esri Calcite 设计系统版本与集成边界

### 固定软件包版本并检查许可要求

Components 5.1.2 和 design tokens 4.1.0 是不同的软件包。当前许可页面说明，使用这些软件包需要 ArcGIS Online、Enterprise 或 Location Platform 账户。不要将对旧版开源发行版的假设套用到当前软件包上。以下原生代码示例适用于满足这些要求的项目。

- Components：5.1.2。

- 设计令牌参考：4.1.0。

- 预览：独立的 HTML、CSS 和 JavaScript；不包含 Esri 运行时。

### 仅注册实际使用的组件

最简模块示例会导入输入组件和按钮组件的入口，然后使用它们公开的属性和事件。完整的独立 HTML 示例可单独运行；原生代码片段则适用于已安装固定版本软件包的 Vite 项目，可作为另一种入口。该示例已根据公开的 API 进行核对，但不应将其描述为示意图背后的编译运行时。

## Esri Calcite 设计系统组件示例

### 独立站点检查示例

本预览使用的完整独立 HTML、CSS 和 JavaScript。将其保存为 index.html 并在浏览器中打开。

```
<!doctype html>
<html lang="en">
  <meta charset="utf-8" /><meta
    name="viewport"
    content="width=device-width,initial-scale=1"
  /><title>Site inspection panel</title
  ><style>
    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
      font:
        14px/1.5 Arial,
        sans-serif;
      color: #141414;
      background: #f7f7f7;
    }
    button,
    input,
    select,
    textarea {
      font: inherit;
    }
    button {
      cursor: pointer;
    }
    button:focus-visible,
    input:focus-visible,
    select:focus-visible,
    textarea:focus-visible {
      outline: 2px solid #007ac2;
      outline-offset: 3px;
    }
    header {
      padding: 20px 24px;
      background: #fff;
      border-bottom: 1px solid #d4d4d4;
      display: flex;
      justify-content: space-between;
      gap: 16px;
      align-items: center;
    }
    h1 {
      font-size: 20px;
      margin: 0;
    }
    header p {
      margin: 2px 0 0;
      color: #6b6b6b;
      font-size: 12px;
    }
    .badge {
      background: #d6efff;
      color: #004874;
      padding: 4px 8px;
      font-size: 12px;
    }
    .layout {
      display: grid;
      grid-template-columns: 240px minmax(0, 1fr) 280px;
      min-height: 510px;
    }
    .sites,
    .inspector {
      background: #fff;
      padding: 20px;
      border-right: 1px solid #d4d4d4;
    }
    .inspector {
      border-right: 0;
      border-left: 1px solid #d4d4d4;
    }
    h2 {
      font-size: 16px;
      margin: 0 0 16px;
    }
    label {
      display: block;
      font-weight: 600;
      margin: 12px 0 6px;
    }
    select,
    textarea {
      width: 100%;
      border: 1px solid #949494;
      background: #fff;
      padding: 8px;
      color: inherit;
    }
    textarea {
      resize: vertical;
      min-height: 96px;
    }
    .site {
      display: block;
      width: 100%;
      text-align: left;
      background: #fff;
      border: 1px solid #dedede;
      padding: 12px;
      margin-top: 8px;
    }
    .site[aria-pressed="true"] {
      border-left: 4px solid #007ac2;
      background: #d6efff;
    }
    .site small {
      display: block;
      color: #4a4a4a;
      margin-top: 3px;
    }
    .map {
      position: relative;
      overflow: hidden;
      min-height: 360px;
      background: #ebebe5;
    }
    .map svg {
      width: 100%;
      height: 100%;
      position: absolute;
      inset: 0;
    }
    .map-caption {
      position: absolute;
      bottom: 12px;
      left: 12px;
      padding: 4px 8px;
      background: #fff;
      font-size: 12px;
    }
    .pin {
      position: absolute;
      width: 36px;
      height: 36px;
      border-radius: 50%;
      border: 3px solid #fff;
      background: #007ac2;
      color: #fff;
      font-weight: bold;
      box-shadow: 0 2px 8px #0004;
    }
    .pin[aria-pressed="true"] {
      background: #004874;
      outline: 3px solid #007ac2;
      outline-offset: 3px;
    }
    .pin[hidden] {
      display: none;
    }
    dl {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 8px;
      font-size: 12px;
    }
    dt {
      color: #6b6b6b;
    }
    dd {
      margin: 0;
      text-align: right;
    }
    .primary {
      background: #007ac2;
      color: white;
      border: 0;
      width: 100%;
      padding: 10px;
      margin-top: 12px;
    }
    .primary:hover {
      background: #00619b;
    }
    .error {
      color: #a11b1b;
      font-size: 12px;
    }
    .saved {
      color: #237000;
      font-size: 12px;
    }
    footer {
      padding: 16px 24px;
      border-top: 1px solid #d4d4d4;
      color: #6b6b6b;
      font-size: 12px;
      background: #fff;
    }
    @media (max-width: 1000px) {
      .layout {
        grid-template-columns: 210px minmax(0, 1fr);
      }
      .inspector {
        grid-column: 1/-1;
        border-left: 0;
        border-top: 1px solid #d4d4d4;
      }
      .inspector form {
        max-width: 640px;
      }
    }
    @media (max-width: 550px) {
      header {
        align-items: flex-start;
        flex-direction: column;
      }
      .layout {
        display: flex;
        flex-direction: column;
      }
      .sites {
        border-right: 0;
      }
      .map {
        height: 300px;
        min-height: 300px;
      }
      .inspector {
        padding: 20px;
      }
      .site {
        display: inline-block;
        width: 100%;
      }
    }
  </style>
  <body>
    <header>
      <div>
        <h1>Field inspection workspace</h1>
        <p>Original Calcite-inspired layout study · fictional site data</p>
      </div>
      <span class="badge">Local notes only</span>
    </header>
    <main class="layout">
      <aside class="sites">
        <h2>Inspection sites</h2>
        <label for="filter">Show sites</label
        ><select id="filter">
          <option value="all">All sites</option>
          <option value="review">Needs review</option>
          <option value="checked">Checked</option>
        </select>
        <div id="site-list"></div>
        <p id="count" aria-live="polite"></p>
      </aside>
      <section class="map" aria-label="Illustrated site plan">
        <svg
          viewBox="0 0 700 510"
          preserveAspectRatio="xMidYMid slice"
          role="img"
          aria-label="Original schematic with a river, roads and three inspection sites; not a geographic map"
        >
          <rect width="700" height="510" fill="#e4e8db" />
          <path
            d="M480 -50Q230 110 440 260T360 570"
            fill="none"
            stroke="#b6dbe9"
            stroke-width="100"
          />
          <path
            d="M-20 150L720 280M160 -20L290 530M-20 400L720 80"
            stroke="#fff"
            stroke-width="22"
          />
          <path
            d="M-20 150L720 280M160 -20L290 530M-20 400L720 80"
            stroke="#c8c8bf"
            stroke-width="2"
          />
          <g fill="#c4cfb5">
            <rect x="50" y="50" width="100" height="70" />
            <rect x="510" y="340" width="130" height="80" />
            <rect x="80" y="260" width="70" height="60" />
          </g>
        </svg>
        <div id="pins"></div>
        <span class="map-caption">Schematic illustration · not to scale</span>
      </section>
      <aside class="inspector">
        <h2 id="site-title">North access</h2>
        <dl>
          <dt>Site ID</dt>
          <dd id="site-id"></dd>
          <dt>Review state</dt>
          <dd id="site-state"></dd>
        </dl>
        <form id="note-form" novalidate>
          <label for="note">Inspection note</label
          ><textarea
            id="note"
            aria-describedby="note-help error"
            maxlength="240"
          ></textarea>
          <p id="note-help">
            Add 10–240 characters. Notes stay in this page until reload.
          </p>
          <p id="error" class="error" hidden>
            Write at least 10 characters before saving.
          </p>
          <button class="primary" type="submit">Save local note</button>
          <p id="saved" class="saved" role="status"></p>
        </form>
      </aside>
    </main>
    <footer>
      Independent HTML/CSS interpretation by OpenDesign. No Calcite runtime,
      Esri fonts, ArcGIS map or service is loaded.
    </footer>
    <script>
      const sites = [
        { id: "A-01", name: "North access", state: "review", x: 29, y: 24 },
        { id: "B-02", name: "River crossing", state: "review", x: 62, y: 48 },
        { id: "C-03", name: "South garden", state: "checked", x: 34, y: 76 },
      ];
      let selected = "A-01";
      const notes = new Map(),
        list = document.querySelector("#site-list"),
        pins = document.querySelector("#pins"),
        filter = document.querySelector("#filter"),
        note = document.querySelector("#note"),
        error = document.querySelector("#error"),
        saved = document.querySelector("#saved");
      function render() {
        const visible = sites.filter(
          (s) => filter.value === "all" || s.state === filter.value,
        );
        if (!visible.some((s) => s.id === selected)) selected = visible[0]?.id;
        list.replaceChildren();
        pins.replaceChildren();
        for (const s of visible) {
          const b = document.createElement("button");
          b.type = "button";
          b.className = "site";
          b.setAttribute("aria-pressed", String(s.id === selected));
          b.textContent = s.name;
          const small = document.createElement("small");
          small.textContent =
            s.id + " · " + (s.state === "review" ? "Needs review" : "Checked");
          b.append(small);
          b.onclick = () => {
            selected = s.id;
            render();
          };
          list.append(b);
          const pin = document.createElement("button");
          pin.type = "button";
          pin.className = "pin";
          pin.style.left = s.x + "%";
          pin.style.top = s.y + "%";
          pin.textContent = s.id[0];
          pin.setAttribute("aria-label", "Select " + s.name);
          pin.setAttribute("aria-pressed", String(s.id === selected));
          pin.onclick = b.onclick;
          pins.append(pin);
        }
        const s = sites.find((s) => s.id === selected);
        document.querySelector("#count").textContent =
          visible.length + " sites shown";
        document.querySelector("#site-title").textContent = s.name;
        document.querySelector("#site-id").textContent = s.id;
        document.querySelector("#site-state").textContent =
          s.state === "review" ? "Needs review" : "Checked";
        note.value = notes.get(s.id) || "";
        error.hidden = true;
        note.removeAttribute("aria-invalid");
        saved.textContent = "";
      }
      filter.onchange = render;
      note.oninput = () => {
        error.hidden = true;
        note.removeAttribute("aria-invalid");
        saved.textContent = "";
      };
      document.querySelector("#note-form").onsubmit = (e) => {
        e.preventDefault();
        const value = note.value.trim();
        if (value.length < 10) {
          error.hidden = false;
          note.setAttribute("aria-invalid", "true");
          note.focus();
          return;
        }
        notes.set(selected, value);
        saved.textContent = "Note saved locally for " + selected + ".";
      };
      render();
    </script>
  </body>
</html>
```

代码参考

- 原始示意图和应用行为。不包含地图 SDK、远程数据或 Esri 运行时。

### Calcite 原生输入替代方案

在 Vite 原生项目中替换 src/main.js；该项目的 index.html 中应包含 <div id="app"></div>。

```
import "@esri/calcite-components/components/calcite-input";
import "@esri/calcite-components/components/calcite-button";

document.querySelector("#app").innerHTML = `
  <calcite-input id="inspection-note" label-text="Inspection note"
    validation-message="Enter at least ten characters"></calcite-input>
  <calcite-button id="save-note">Validate note</calcite-button>
  <p id="result" role="status"></p>`;
const field = document.querySelector("#inspection-note");
const result = document.querySelector("#result");
field.addEventListener("calciteInputInput", () => {
  field.status = "idle";
  result.textContent = "";
});
document.querySelector("#save-note").addEventListener("click", async () => {
  if (field.value.trim().length < 10) {
    field.status = "invalid";
    await field.setFocus();
    return;
  }
  field.status = "valid";
  result.textContent = "The note passes the local rule. Nothing was sent.";
});
```

代码参考

- 查看当前许可要求后，安装 @esri/calcite-components@5.1.2。此替代方案已通过 API 检查；上方的独立预览则是在浏览器中测试过的示例。

## Esri Calcite 设计系统 AI Agent 设置

### 实现起点

根据当前许可条款，使用原生组件软件包需要符合条件的 ArcGIS 账户。自行托管组件资源时，请查看资源路径要求。

```
# Independent specimen: save the complete HTML example as index.html.
# Native alternative for an appropriately licensed project:
npm create vite@latest calcite-note -- --template vanilla
cd calcite-note
npm install
npm install @esri/calcite-components@5.1.2
# Replace src/main.js with the native input example.
npm run dev
```

### 适用于你项目的提示词

```
使用 Calcite 参考资料构建一个专注于空间信息检查的工作区。确保列表和检查器中的所选对象 ID 保持一致，明确展示各项状态，并区分本地备注与服务端持久化。可以从独立实现开始，也可以明确选择符合许可要求的原生组件方案。不要将原始示意图描述为 ArcGIS 地图。
```

## Esri Calcite 设计系统来源与适用范围

OpenDesign 应用指南。图示示例为独立实现，使用虚构数据。当前使用 Calcite 受 Esri 许可条款约束，并需要符合条件的 ArcGIS 账户；原生集成示例适用于符合许可要求的项目，并非本预览所用的运行时。

- Calcite 输入 API 字段属性、事件和焦点方法。

- Calcite 入门指南 组件注册和资源设置。

- 当前许可 ArcGIS 账户与使用要求。

- 已发布的设计令牌 固定版本的字体、间距和圆角参考。

## Esri Calcite 设计系统相关资源

### GitLab Pajamas

面向技术工作流的 Pajamas 指南：真实的语义令牌、流畅的字号与间距、分阶段的流水线检查器、清晰易读的失败输出，以及明确限定在本地的重试模拟。

### HPE Grommet

使用 Grommet 的布局基元、受控表单字段和数值仪表来构建容量预留界面。谨慎使用其主题比例，并将 Grommet 基础主题与单独安装的 HPE 主题区分开来。

### Infor 设计系统

使用真实的 IDS 输入状态、主题别名和准确的资源标识符，构建企业级维护表单。查看当前公开的主题令牌、固定版本的 Web Components 软件包，以及包含验证和重置功能的本地草稿工作流。


- [实现参考](https://developers.arcgis.com/calcite-design-system/)
- [来源](https://cdn.jsdelivr.net/npm/@esri/calcite-design-tokens@4.1.0/dist/css/light.css)
- [来源](https://cdn.jsdelivr.net/npm/@esri/calcite-design-tokens@4.1.0/dist/css/global.css)
- [来源](https://developers.arcgis.com/calcite-design-system/components/input/)
- [代码参考](https://cdn.jsdelivr.net/npm/@esri/calcite-design-tokens@4.1.0/dist/css/light.css)
- [代码参考](https://developers.arcgis.com/calcite-design-system/components/input/)
- [Calcite 输入 API 字段属性、事件和焦点方法。](https://developers.arcgis.com/calcite-design-system/components/input/)
- [Calcite 入门指南 组件注册和资源设置。](https://developers.arcgis.com/calcite-design-system/get-started/)
- [当前许可 ArcGIS 账户与使用要求。](https://developers.arcgis.com/calcite-design-system/resources/licensing/)
- [已发布的设计令牌 固定版本的字体、间距和圆角参考。](https://cdn.jsdelivr.net/npm/@esri/calcite-design-tokens@4.1.0/dist/css/global.css)
