# yatra/3.0.8/assets/dist/blocks/tour.js

Yatra – Travel Booking &amp; Tour Operator Software, version 3.0.8. 580 lines.

- Page: https://pluginprobe.com/plugins/yatra/3.0.8/code/assets/dist/blocks/tour.js
- Raw: https://pluginprobe.com/plugins/yatra/3.0.8/raw/assets/dist/blocks/tour.js
- Modified: 2026-05-25T04:28:24+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/yatra/3.0.8/code/assets/dist/blocks/tour.js#L10-L20`.

```javascript
(function(element, blocks, blockEditor, components, i18n, ServerSideRender, apiFetch) {
  "use strict";
  const listWrapStyle = {
    maxHeight: 220,
    overflowY: "auto",
    marginTop: 8,
    padding: "4px 0",
    border: "1px solid #94949451",
    borderRadius: 2
  };
  function ClassificationMultiSelect({
    taxonomy,
    label,
    help,
    value,
    onChange
  }) {
    const [items, setItems] = element.useState([]);
    const [loading, setLoading] = element.useState(true);
    const [loadError, setLoadError] = element.useState(false);
    const [search, setSearch] = element.useState("");
    const [scope, setScope] = element.useState(
      () => value.length > 0 ? "narrow" : "all"
    );
    element.useEffect(() => {
      if (value.length > 0) {
        setScope("narrow");
      }
    }, [value.length]);
    element.useEffect(() => {
      let cancelled = false;
      setLoading(true);
      setLoadError(false);
      apiFetch({
        path: `/yatra/v1/block-editor/taxonomy-choices?taxonomy=${encodeURIComponent(
          taxonomy
        )}`
      }).then((response) => {
        if (!cancelled) {
          setItems(response.items ?? []);
        }
      }).catch(() => {
        if (!cancelled) {
          setItems([]);
          setLoadError(true);
        }
      }).finally(() => {
        if (!cancelled) {
          setLoading(false);
        }
      });
      return () => {
        cancelled = true;
      };
    }, [taxonomy]);
    const filteredItems = element.useMemo(() => {
      const q = search.trim().toLowerCase();
      if (q === "") {
        return items;
      }
      return items.filter((i) => i.name.toLowerCase().includes(q));
    }, [items, search]);
    const selectedSet = element.useMemo(() => new Set(value), [value]);
    const toggleId = (id, checked) => {
      const next = new Set(selectedSet);
      if (checked) {
        next.add(id);
      } else {
        next.delete(id);
      }
      onChange([...next].sort((a, b) => a - b));
    };
    const onScopeChange = (next) => {
      if (next === "all") {
        setScope("all");
        onChange([]);
        setSearch("");
      } else {
        setScope("narrow");
      }
    };
    if (loading) {
      return /* @__PURE__ */ element.createElement(
        "fieldset",
        {
          className: "yatra-block-taxonomy-field",
          style: { margin: "0 0 16px", border: "none", padding: 0 }
        },
        /* @__PURE__ */ element.createElement(
          "legend",
          {
            className: "components-base-control__label",
            style: { padding: 0 }
          },
          label
        ),
        /* @__PURE__ */ element.createElement(components.Spinner, null)
      );
    }
    return /* @__PURE__ */ element.createElement(
      "fieldset",
      {
        className: "yatra-block-taxonomy-field",
        style: { margin: "0 0 16px", border: "none", padding: 0 }
      },
      /* @__PURE__ */ element.createElement("legend", { className: "components-base-control__label", style: { padding: 0 } }, label),
      /* @__PURE__ */ element.createElement(
        "p",
        {
          className: "components-base-control__help",
          style: { marginTop: 4, marginBottom: 10 }
        },
        help
      ),
      loadError && /* @__PURE__ */ element.createElement("p", { style: { color: "#b32d2e", fontSize: 12, marginBottom: 8 } }, i18n.__(
        "Could not load options. Confirm you can edit posts and Yatra REST is available.",
        "yatra"
      )),
      /* @__PURE__ */ element.createElement(
        components.RadioControl,
        {
          label: i18n.__("Listing scope", "yatra"),
          selected: scope,
          options: [
            {
              label: i18n.__("All published (no restriction)", "yatra"),
              value: "all"
            },
            {
              label: i18n.__("Only selected (search below)", "yatra"),
              value: "narrow"
            }
          ],
          onChange: onScopeChange
        }
      ),
      scope === "all" && /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help", style: { marginTop: 4 } }, i18n.__(
        "The frontend will include every matching published item.",
        "yatra"
      )),
      scope === "narrow" && /* @__PURE__ */ element.createElement(element.Fragment, null, /* @__PURE__ */ element.createElement(
        components.SearchControl,
        {
          label: i18n.sprintf(
            /* translators: %d = number of loaded taxonomy items */
            i18n.__("Filter items (%d loaded)", "yatra"),
            items.length
          ),
          hideLabelFromVision: true,
          placeholder: i18n.__("Type to filter the list…", "yatra"),
          value: search,
          onChange: (s) => setSearch(s),
          __nextHasNoMarginBottom: true
        }
      ), value.length > 0 && /* @__PURE__ */ element.createElement(
        "p",
        {
          className: "components-base-control__help",
          style: { marginTop: 4 }
        },
        i18n.sprintf(
          /* translators: %d = number of selected taxonomy items */
          i18n.__("%d selected", "yatra"),
          value.length
        )
      ), items.length === 0 && !loadError ? /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help" }, i18n.__("No published items of this type yet.", "yatra")) : /* @__PURE__ */ element.createElement("div", { role: "group", "aria-label": label, style: listWrapStyle }, filteredItems.length === 0 ? /* @__PURE__ */ element.createElement("p", { style: { padding: "8px 12px", margin: 0, fontSize: 12 } }, i18n.__("No matching items.", "yatra")) : filteredItems.map((item) => {
        const cid = Number(item.id);
        return /* @__PURE__ */ element.createElement("div", { key: cid, style: { padding: "2px 8px" } }, /* @__PURE__ */ element.createElement(
          components.CheckboxControl,
          {
            label: `${item.name} (${cid})`,
            checked: selectedSet.has(cid),
            onChange: (checked) => toggleId(cid, checked === true),
            __nextHasNoMarginBottom: true
          }
        ));
      })), value.length > 0 && /* @__PURE__ */ element.createElement(
        components.Button,
        {
          variant: "link",
          style: { paddingLeft: 0, marginTop: 6 },
          onClick: () => onChange([])
        },
        i18n.__("Clear selected", "yatra")
      ), /* @__PURE__ */ element.createElement("p", { className: "components-base-control__help", style: { marginTop: 6 } }, i18n.__(
        "If none are checked, the block behaves like “All” (no taxonomy filter).",
        "yatra"
      )))
    );
  }
  function migrateNumericCsvPairToIds(legacyA, legacyB) {
    const raw = [legacyA ?? "", legacyB ?? ""].find(
      (s) => String(s).trim() !== ""
    );
    if (raw === void 0) {
      return [];
    }
    const parts = String(raw).split(",").map((s) => s.trim()).filter(Boolean);
    const ids = [];
    for (const p of parts) {
      if (!/^\d+$/.test(p)) {
        return [];
      }
      const n = parseInt(p, 10);
      if (n > 0) {
        ids.push(n);
      }
    }
    return [...new Set(ids)];
  }
  function normalizeIds(arr) {
    return Array.isArray(arr) ? [...new Set(arr.map((n) => parseInt(String(n), 10)).filter((n) => n > 0))] : [];
  }
  function Edit({ attributes: attributes2, setAttributes }) {
    const migratedOnce = element.useRef(false);
    element.useEffect(() => {
      if (migratedOnce.current) {
        return;
      }
      migratedOnce.current = true;
      const clears = {};
      let destIds = normalizeIds(attributes2.destinationIds);
      if (destIds.length === 0) {
        destIds = migrateNumericCsvPairToIds(
          attributes2.destination_ids,
          attributes2.destination
        );
        if (destIds.length) {
          clears.destination = "";
          clears.destination_ids = "";
        }
      }
      let actIds = normalizeIds(attributes2.activityIds);
      if (actIds.length === 0) {
        actIds = migrateNumericCsvPairToIds(
          attributes2.activity_ids,
          attributes2.activity
        );
        if (actIds.length) {
          clears.activity = "";
          clears.activity_ids = "";
        }
      }
      let catIds = normalizeIds(attributes2.categoryIds);
      if (catIds.length === 0) {
        catIds = migrateNumericCsvPairToIds(
          attributes2.category_ids,
          attributes2.category
        );
        if (catIds.length) {
          clears.category = "";
          clears.category_ids = "";
        }
      }
      let diffIds = normalizeIds(attributes2.difficultyIds);
      if (diffIds.length === 0) {
        const fromDiff = migrateNumericCsvPairToIds(attributes2.difficulty, "");
        diffIds = fromDiff;
        if (fromDiff.length) {
          clears.difficulty = "";
        }
      }
      if (attributes2.featured && !attributes2.featured_priority) {
        clears.featured_priority = "featured";
        clears.featured = false;
      }
      const next = { ...clears };
      if (destIds.length) {
        next.destinationIds = destIds;
      }
      if (actIds.length) {
        next.activityIds = actIds;
      }
      if (catIds.length) {
        next.categoryIds = catIds;
      }
      if (diffIds.length) {
        next.difficultyIds = diffIds;
      }
      const touched = Object.keys(next).filter(
        (key) => next[key] !== void 0
      ).length > 0;
      if (touched) {
        setAttributes(next);
      }
    }, [setAttributes]);
    const destinationIds = normalizeIds(attributes2.destinationIds);
    const activityIds = normalizeIds(attributes2.activityIds);
    const categoryIds = normalizeIds(attributes2.categoryIds);
    const difficultyIds = normalizeIds(attributes2.difficultyIds);
    return /* @__PURE__ */ element.createElement(element.Fragment, null, /* @__PURE__ */ element.createElement(blockEditor.InspectorControls, null, /* @__PURE__ */ element.createElement(components.PanelBody, { title: i18n.__("Trip Settings", "yatra"), initialOpen: true }, /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Title", "yatra"),
        value: attributes2.title,
        onChange: (value) => setAttributes({ title: value })
      }
    ), /* @__PURE__ */ element.createElement(
      components.SelectControl,
      {
        label: i18n.__("Order", "yatra"),
        value: attributes2.order,
        options: [
          { label: i18n.__("Descending", "yatra"), value: "desc" },
          { label: i18n.__("Ascending", "yatra"), value: "asc" }
        ],
        onChange: (value) => setAttributes({ order: value })
      }
    ), /* @__PURE__ */ element.createElement(
      components.RangeControl,
      {
        label: i18n.__("Number of Trips", "yatra"),
        value: attributes2.per_page,
        onChange: (value) => setAttributes({ per_page: value || 10 }),
        min: 1,
        max: 50
      }
    ), /* @__PURE__ */ element.createElement(
      components.RangeControl,
      {
        label: i18n.__("Columns", "yatra"),
        value: attributes2.columns,
        onChange: (value) => setAttributes({
          columns: value !== void 0 && value !== null ? value : 3
        }),
        min: 1,
        max: 6
      }
    ), /* @__PURE__ */ element.createElement(
      components.SelectControl,
      {
        label: i18n.__("Featured Priority", "yatra"),
        help: i18n.__(
          "Restrict to trips marked with a specific priority on the trip form (Categorization → Featured Priority). Choose Any to show all trips.",
          "yatra"
        ),
        value: attributes2.featured_priority || "",
        options: [
          { label: i18n.__("Any", "yatra"), value: "" },
          { label: i18n.__("Featured", "yatra"), value: "featured" },
          { label: i18n.__("New", "yatra"), value: "new" },
          { label: i18n.__("Limited Time", "yatra"), value: "limited" }
        ],
        onChange: (value) => setAttributes({
          featured_priority: value,
          // Keep legacy `featured` boolean in sync for back-compat
          // (existing block instances saved with featured=true).
          featured: value === "featured"
        })
      }
    ), /* @__PURE__ */ element.createElement(
      components.ToggleControl,
      {
        label: i18n.__("Show pagination", "yatra"),
        checked: attributes2.show_pagination,
        onChange: (value) => setAttributes({ show_pagination: value })
      }
    )), /* @__PURE__ */ element.createElement(components.PanelBody, { title: i18n.__("Filters", "yatra"), initialOpen: false }, /* @__PURE__ */ element.createElement(
      ClassificationMultiSelect,
      {
        taxonomy: "destination",
        label: i18n.__("Destinations", "yatra"),
        help: i18n.__(
          'Choose "All published" or restrict the grid to destinations you tick. Other filters narrow results further.',
          "yatra"
        ),
        value: destinationIds,
        onChange: (ids) => setAttributes({ destinationIds: ids })
      }
    ), /* @__PURE__ */ element.createElement(
      ClassificationMultiSelect,
      {
        taxonomy: "activity",
        label: i18n.__("Activities", "yatra"),
        help: i18n.__(
          "Optional. When restricting, trips must match every classification filter that has selections.",
          "yatra"
        ),
        value: activityIds,
        onChange: (ids) => setAttributes({ activityIds: ids })
      }
    ), /* @__PURE__ */ element.createElement(
      ClassificationMultiSelect,
      {
        taxonomy: "trip_category",
        label: i18n.__("Trip categories", "yatra"),
        help: i18n.__(
          "Yatra trip types (not WooCommerce categories). Combine with destinations/activities if needed.",
          "yatra"
        ),
        value: categoryIds,
        onChange: (ids) => setAttributes({ categoryIds: ids })
      }
    ), /* @__PURE__ */ element.createElement(
      ClassificationMultiSelect,
      {
        taxonomy: "difficulty",
        label: i18n.__("Difficulty levels", "yatra"),
        help: i18n.__(
          "Optional. When restricting, trips must use one of the selected difficulty classifications.",
          "yatra"
        ),
        value: difficultyIds,
        onChange: (ids) => setAttributes({ difficultyIds: ids })
      }
    ), /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Search", "yatra"),
        value: attributes2.search,
        onChange: (v) => setAttributes({ search: v })
      }
    ), /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Price min", "yatra"),
        type: "number",
        value: attributes2.price_min,
        onChange: (v) => setAttributes({ price_min: v })
      }
    ), /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Price max", "yatra"),
        type: "number",
        value: attributes2.price_max,
        onChange: (v) => setAttributes({ price_max: v })
      }
    ), /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Duration min (days)", "yatra"),
        type: "number",
        value: attributes2.duration_min,
        onChange: (v) => setAttributes({ duration_min: v })
      }
    ), /* @__PURE__ */ element.createElement(
      components.TextControl,
      {
        label: i18n.__("Duration max (days)", "yatra"),
        type: "number",
        value: attributes2.duration_max,
        onChange: (v) => setAttributes({ duration_max: v })
      }
    ))), /* @__PURE__ */ element.createElement("div", { className: "yatra-block-editor-preview" }, /* @__PURE__ */ element.createElement(
      ServerSideRender,
      {
        block: "yatra/tour",
        attributes: attributes2,
        key: JSON.stringify(attributes2)
      }
    )));
  }
  const $schema = "https://schemas.wp.org/trunk/block.json";
  const apiVersion = 3;
  const name = "yatra/tour";
  const title = "Trip";
  const category = "yatra";
  const icon = "palmtree";
  const description = "Display trip listings with customizable options";
  const keywords = [
    "tour",
    "trip",
    "trips",
    "tours",
    "travel",
    "yatra"
  ];
  const textdomain = "yatra";
  const attributes = {
    order: {
      type: "string",
      "default": "desc"
    },
    featured: {
      type: "boolean",
      "default": false
    },
    featured_priority: {
      type: "string",
      "default": "",
      "enum": [
        "",
        "featured",
        "new",
        "limited"
      ]
    },
    per_page: {
      type: "number",
      "default": 10
    },
    columns: {
      type: "number",
      "default": 3
    },
    title: {
      type: "string",
      "default": "Our Trips"
    },
    show_pagination: {
      type: "boolean",
      "default": true
    },
    destinationIds: {
      type: "array",
      "default": []
    },
    activityIds: {
      type: "array",
      "default": []
    },
    categoryIds: {
      type: "array",
      "default": []
    },
    difficultyIds: {
      type: "array",
      "default": []
    },
    price_min: {
      type: "string",
      "default": ""
    },
    price_max: {
      type: "string",
      "default": ""
    },
    duration_min: {
      type: "string",
      "default": ""
    },
    duration_max: {
      type: "string",
      "default": ""
    },
    search: {
      type: "string",
      "default": ""
    }
  };
  const supports = {
    html: false,
    inserter: true,
    align: [
      "wide",
      "full"
    ]
  };
  const editorScript = "yatra-tour-block-editor";
  const blockMetadata = {
    $schema,
    apiVersion,
    name,
    title,
    category,
    icon,
    description,
    keywords,
    textdomain,
    attributes,
    supports,
    editorScript
  };
  const {
    $schema: _$schema,
    editorScript: _$editorScript,
    ...metadata
  } = blockMetadata;
  if (blocks.getBlockType(metadata.name)) {
    blocks.unregisterBlockType(metadata.name);
  }
  blocks.registerBlockType(metadata.name, {
    ...metadata,
    edit: Edit,
    save: () => null
  });
})(wp.element, wp.blocks, wp.blockEditor, wp.components, wp.i18n, wp.serverSideRender, wp.apiFetch);
//# sourceMappingURL=tour.js.map

```
