lodash#isNull TypeScript Examples

The following examples show how to use lodash#isNull. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: time-series.utils.ts    From aqualink-app with MIT License 7 votes vote down vote up
groupByMetricAndSource = <T extends TimeSeriesGroupable>(
  data: T[],
): TimeSeriesResponse<
  Omit<T, 'metric' | 'source' | 'surveyPointId' | 'surveyPointName'>
> => {
  return _(data)
    .groupBy('metric')
    .mapValues((grouped) => {
      return _(grouped)
        .groupBy('source')
        .mapValues((groupedData) => {
          const { surveyPointId, surveyPointName } = last(groupedData) || {};
          return merge(
            !isNull(surveyPointId)
              ? { surveyPoint: { id: surveyPointId, name: surveyPointName } }
              : {},
            {
              data: groupedData
                .filter((o) =>
                  typeof surveyPointId === 'number'
                    ? surveyPointId === o.surveyPointId
                    : true,
                )
                .map((o) =>
                  omit(
                    o,
                    'metric',
                    'source',
                    'surveyPointId',
                    'surveyPointName',
                  ),
                ),
            },
          );
        })
        .toJSON();
    })
    .toJSON();
}
Example #2
Source File: utils.ts    From gant-design with MIT License 7 votes vote down vote up
isEqualObj = (obj, obj2) => {
  let _EqualObj = true;
  if (!isPlainObject(obj) || !isPlainObject(obj2)) {
    if (isEmptyObj(obj) && isEmptyObj(obj2)) return true;
    return isEqual(obj, obj2);
  }
  if (isNull(obj) && isNull(obj2)) return true;
  if (isNull(obj) || isNull(obj2)) {
    return false;
  }
  const newObj = { ...obj, ...obj2 };
  for (let i in newObj) {
    let value1 = get(obj, i),
      value2 = get(obj2, i);
    if (
      typeof value1 === 'object' &&
      typeof value2 === 'object' &&
      !Array.isArray(value1) &&
      !Array.isArray(value2)
    ) {
      _EqualObj = isEqualObj(value1, value2);
    } else {
      if (!(isEmptyObj(value1) && isEmptyObj(value2))) {
        value2 = typeof value2 == 'number' ? value2 : value2 + '';
        value1 = typeof value1 == 'number' ? value1 : value1 + '';
        _EqualObj = isEqual(value2, value1);
      }
    }
    if (!_EqualObj) {
      return _EqualObj;
    }
  }
  return true;
}
Example #3
Source File: analytics.ts    From hub with Apache License 2.0 6 votes vote down vote up
getPlugins = (): AnalyticsPlugin[] => {
  let plugins: AnalyticsPlugin[] = [];
  const analyticsConfig: string | null = getMetaTag('gaTrackingID');

  if (!isNull(analyticsConfig) && analyticsConfig !== '' && analyticsConfig !== '{{ .gaTrackingID }}') {
    plugins.push(
      googleAnalytics({
        trackingId: analyticsConfig,
      })
    );
  }

  return plugins;
}
Example #4
Source File: update-one-user-search-group.ts    From js-client with MIT License 6 votes vote down vote up
makeUpdateOneUserSearchGroup = (context: APIContext) => {
	return async (userID: NumericID, groupID: NumericID | null): Promise<void> => {
		try {
			const path = '/api/users/{userID}/searchgroup';
			const url = buildURL(path, { ...context, protocol: 'http', pathParams: { userID } });

			const body: UpdateOneUserSearchGroupRawRequest = {
				GID: isNumber(groupID) ? groupID : isNull(groupID) ? groupID : parseInt(groupID, 10),
			};

			const baseRequestOptions: HTTPRequestOptions = {
				body: JSON.stringify(body),
			};
			const req = buildHTTPRequestWithAuthFromContext(context, baseRequestOptions);

			const raw = await context.fetch(url, { ...req, method: 'PUT' });
			return parseJSONResponse(raw, { expect: 'void' });
		} catch (err) {
			if (err instanceof Error) throw err;
			throw Error('Unknown error');
		}
	};
}
Example #5
Source File: event.ts    From visual-layout with MIT License 6 votes vote down vote up
onDrop = (node: NodeService) => (ev: React.DragEvent) => {
    ev.preventDefault();
    ev.stopPropagation();
    const id = ev.dataTransfer?.getData(DragEleId);
    if (id) {
      const nodeService: NodeService = Reflect.get(DocEvent.dragData, id);
      if (nodeService) {
        Reflect.deleteProperty(DocEvent.dragData, id);
        // up merge
        node.styles.push(...nodeService.styles);

        const children = isString(node.children)
          ? [node.children]
          : node.children || [];

        !isNull(children) &&
          children?.push(
            ...((isString(nodeService.children)
              ? [nodeService.children]
              : nodeService.children?.filter(_ => _)) || []),
          );

        if (!isNull(node.children)) {
          node.children = children;
        }
      }

      node.getPageServiceInstance()?.update({ description: '添加元素' });
    }
  };
Example #6
Source File: ikea-onoff-switch.ts    From homebridge-zigbee-nt with Apache License 2.0 6 votes vote down vote up
update(state: DeviceState): void {
    const Characteristic = this.platform.Characteristic;
    const ProgrammableSwitchEvent = Characteristic.ProgrammableSwitchEvent;
    if (!isNull(state.battery) && !isUndefined(state.battery)) {
      this.batteryService.updateCharacteristic(Characteristic.BatteryLevel, state.battery || 0);
      this.batteryService.updateCharacteristic(
        Characteristic.StatusLowBattery,
        state.battery && state.battery < 10
      );
    }
    switch (state.action) {
      case 'brightness_move_up':
        this.switchServiceOn
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
      case 'brightness_move_down':
        this.switchServiceOff
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
      case 'on':
        this.switchServiceOn
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      case 'off':
        this.switchServiceOff
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
    }
  }
Example #7
Source File: balance.ts    From subscan-multisig-react with Apache License 2.0 6 votes vote down vote up
toString = (value: string | BN | number): string => {
  if (BN.isBN(value)) {
    return value.toString();
  } else if (isString(value)) {
    return Number(value).toString(10);
  } else if (isNumber(value)) {
    return value.toString(10);
  } else if (isUndefined(value) || isNaN(value) || isNull(value)) {
    return '0';
  } else {
    throw new TypeError(
      // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
      `Can not convert the value ${value} to String type. Value type is ${typeof value}`
    );
  }
}
Example #8
Source File: analysis-utils.ts    From prism-frontend with MIT License 5 votes vote down vote up
export async function loadFeaturesClientSide(
  api: ThunkApi,
  layer: ImpactLayerProps,
  adminBoundaries: BoundaryLayerData,
  baselineData: BaselineLayerData,
  hazardLayerDef: WMSLayerProps,
  operation: AggregationOperations,
  loadLayerData: LoadLayerDataFuncType,
  extent?: Extent,
  date?: number,
): Promise<GeoJsonBoundary[]> {
  const { getState, dispatch } = api;

  const { wcsConfig } = hazardLayerDef;
  const { noData, scale, offset } = wcsConfig || {};

  const existingHazardLayer = layerDataSelector(
    layer.hazardLayer,
    date,
  )(getState());

  if (!existingHazardLayer) {
    await dispatch(
      loadLayerData({
        layer: hazardLayerDef,
        extent,
        date,
      } as LayerDataParams<WMSLayerProps>),
    );
  }

  const hazardLayer = checkRasterLayerData(
    layerDataSelector(layer.hazardLayer, date)(getState())!,
  );
  const {
    data: { rasters, transform, image },
  } = hazardLayer;

  // Calculate a bounding box for each feature that we have baseline data for
  const matchingFeatures = adminBoundaries.features.reduce(
    (acc, f) => {
      const feature = f as GeoJsonBoundary;
      const baseline =
        featureIntersectsImage(feature, image) &&
        getBaselineDataForFeature(feature, baselineData);
      return baseline
        ? acc.concat({
            id: baseline.adminKey,
            baseline,
            feature,
            bounds: bbox(feature),
          })
        : acc;
    },
    [] as {
      id: string;
      baseline: BaselineRecord;
      feature: GeoJsonBoundary;
      bounds: ReturnType<typeof bbox>;
    }[],
  );

  // Loop over the features and grab pixels that are contained by the feature.
  const buckets = matchingFeatures.reduce((acc, { id, feature }) => {
    const contained = pixelsInFeature(
      feature,
      rasters[0],
      rasters.width,
      transform,
    );
    return contained.length > 0 ? { ...acc, [id]: contained } : acc;
  }, {} as { [key: string]: number[] });

  return matchingFeatures.reduce((acc, { id, feature, baseline }) => {
    const values = buckets[id];

    if (values) {
      const raw = operations[operation](
        noData ? values.filter(value => value !== noData) : values,
      );
      // If the aggregate is not valid, return early
      if (raw === undefined) {
        return acc;
      }
      const scaled = scaleValueIfDefined(raw, scale, offset);
      const aggregateValue = thresholdOrNaN(scaled, layer.threshold);
      if (!Number.isNaN(aggregateValue)) {
        const { properties } = feature;

        const baselineValue = isString(baseline.value)
          ? parseFloat(baseline.value)
          : baseline.value;
        return isNull(baselineValue)
          ? acc
          : acc.concat({
              ...feature,
              properties: {
                ...properties,
                [operation]: aggregateValue,
                impactValue: baselineValue,
              },
            });
      }
    }
    return acc;
  }, [] as GeoJsonBoundary[]);
}
Example #9
Source File: useSystemThemeMode.ts    From hub with Apache License 2.0 5 votes vote down vote up
export default function useSystemThemeMode(enabled: boolean, dispatch: Dispatch<any>) {
  const [mediaQuery, setMediaQuery] = useState<MediaQueryList | null>(null);
  const themeDarkModeFn = useCallback(() => {
    dispatch({ type: 'updateEffectiveTheme', theme: detectActiveThemeMode() });
  }, [dispatch]);

  useEffect(() => {
    const removeListener = () => {
      if (!isNull(mediaQuery)) {
        try {
          mediaQuery.removeEventListener('change', themeDarkModeFn);
        } catch {
          try {
            mediaQuery.removeListener(themeDarkModeFn);
          } catch {
            // Old browser
          }
        }
      }
    };

    if (enabled) {
      const currentMode = window.matchMedia(`(prefers-color-scheme: dark)`);
      setMediaQuery(currentMode);
      try {
        currentMode.addEventListener('change', themeDarkModeFn);
      } catch {
        try {
          currentMode.addListener(themeDarkModeFn);
        } catch {
          // Old browser
        }
      }
    } else {
      removeListener();
    }
    return () => {
      if (!isNull(mediaQuery)) {
        removeListener();
      }
    };
  }, [enabled]); /* eslint-disable-line react-hooks/exhaustive-deps */
}
Example #10
Source File: preview-one-resource-content.spec.ts    From js-client with MIT License 5 votes vote down vote up
describe('previewOneResource()', () => {
	const createOneResource = makeCreateOneResource(TEST_BASE_API_CONTEXT);
	const deleteOneResource = makeDeleteOneResource(TEST_BASE_API_CONTEXT);
	const previewOneResource = makePreviewOneResourceContent(TEST_BASE_API_CONTEXT);
	const setOneResourceContent = makeSetOneResourceContent(TEST_BASE_API_CONTEXT);
	const getOneResourceContent = makeGetOneResourceContent(TEST_BASE_API_CONTEXT);

	let createdResourceID: UUID;
	let createdResourceContent: string;

	beforeEach(async () => {
		const data: CreatableResource = {
			name: 'a name',
			description: 'a description',
		};
		createdResourceID = (await createOneResource(data)).id;

		// Set the content
		const contentLength = 2048;
		createdResourceContent = ''.padEnd(contentLength, 'z');
		await setOneResourceContent(createdResourceID, createdResourceContent as any);
	});

	afterEach(async () => {
		await deleteOneResource(createdResourceID);
	});

	it(
		'Should return a preview of the resource content with the specified bytes',
		integrationTest(async () => {
			const tests = [256, 128, 127, 129, 64, null, 512, 1024, 2048];
			const originalResourceContent = await getOneResourceContent(createdResourceID);
			expect(originalResourceContent).toBe(createdResourceContent);

			const testPromises = tests.map(async bytes => {
				const expectedBytes = isNull(bytes) ? 512 : bytes < 128 ? 512 : bytes;
				const expectedContent = createdResourceContent.substr(0, expectedBytes);
				const preview = await previewOneResource(createdResourceID, { bytes: bytes ?? undefined });

				expect(preview.body.length).toBe(expectedBytes);
				expect(preview.body).toBe(expectedContent);
			});
			await Promise.all(testPromises);
		}),
	);
});
Example #11
Source File: ikea-remote-switch.ts    From homebridge-zigbee-nt with Apache License 2.0 5 votes vote down vote up
update(state: DeviceState): void {
    const Characteristic = this.platform.Characteristic;
    const ProgrammableSwitchEvent = Characteristic.ProgrammableSwitchEvent;
    if (!isNull(state.battery) && !isUndefined(state.battery)) {
      this.batteryService.updateCharacteristic(Characteristic.BatteryLevel, state.battery || 0);
      this.batteryService.updateCharacteristic(
        Characteristic.StatusLowBattery,
        state.battery && state.battery < 10
      );
    }
    switch (state.action) {
      case 'brightness_up_click':
        this.switchServiceBrightUp
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      case 'brightness_down_click':
        this.switchServiceBrightDown
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      case 'toggle':
        this.switchServiceToggle
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      case 'arrow_left_click':
        this.switchServiceLeft
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      case 'arrow_right_click':
        this.switchServiceRight
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.SINGLE_PRESS);
        break;
      // LONG press
      case 'brightness_up_hold':
        this.switchServiceBrightUp
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
      case 'brightness_down_hold':
        this.switchServiceBrightDown
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
      case 'arrow_left_hold':
        this.switchServiceLeft
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
      case 'arrow_right_hold':
        this.switchServiceRight
          .getCharacteristic(ProgrammableSwitchEvent)
          .setValue(ProgrammableSwitchEvent.LONG_PRESS);
        break;
    }
  }
Example #12
Source File: admin_level_data.ts    From prism-frontend with MIT License 4 votes vote down vote up
export function getAdminLevelDataLayerData(
  data: { [key: string]: any }[],
  {
    boundary,
    adminCode,
    dataField,
    featureInfoProps,
  }: Pick<
    AdminLevelDataLayerProps,
    'boundary' | 'adminCode' | 'dataField' | 'featureInfoProps'
  >,
  getState: () => RootState,
) {
  // check unique boundary layer presence into this layer
  // use the boundary once available or
  // use the default boundary singleton instead
  const adminBoundaryLayer =
    boundary !== undefined
      ? (LayerDefinitions[boundary as LayerKey] as BoundaryLayerProps)
      : getBoundaryLayerSingleton();

  const adminBoundariesLayer = layerDataSelector(adminBoundaryLayer.id)(
    getState(),
  ) as LayerData<BoundaryLayerProps> | undefined;
  if (!adminBoundariesLayer || !adminBoundariesLayer.data) {
    // TODO we are assuming here it's already loaded. In the future if layers can be preloaded like boundary this will break.
    throw new Error('Boundary Layer not loaded!');
  }
  const adminBoundaries = adminBoundariesLayer.data;

  const layerData = (data || [])
    .map(point => {
      const adminKey = point[adminCode] as string;
      if (!adminKey) {
        return undefined;
      }
      const value = get(point, dataField);
      const featureInfoPropsValues = Object.keys(featureInfoProps || {}).reduce(
        (obj, item) => {
          return {
            ...obj,
            [item]: point[item],
          };
        },
        {},
      );
      return { adminKey, value, ...featureInfoPropsValues } as DataRecord;
    })
    .filter((v): v is DataRecord => v !== undefined);

  const features = {
    ...adminBoundaries,
    features: adminBoundaries.features
      .map(feature => {
        const { properties } = feature;
        const adminBoundaryCode = get(
          properties,
          adminBoundaryLayer.adminCode,
        ) as string;
        const matchProperties = layerData.find(({ adminKey }) =>
          adminBoundaryCode.startsWith(adminKey),
        );
        if (matchProperties && !isNull(matchProperties.value)) {
          // Do we want support for non-numeric values (like string colors?)
          const value = isString(matchProperties.value)
            ? parseFloat(matchProperties.value)
            : matchProperties.value;
          return {
            ...feature,
            properties: {
              ...properties,
              ...matchProperties,
              // TODO - standardize the field we use to store that data
              // Some functions use "dataField" while others use "data"
              data: value,
              [dataField]: value,
            },
          };
        }
        return undefined;
      })
      .filter(f => f !== undefined),
  } as FeatureCollection;
  return {
    features,
    layerData,
  };
}
Example #13
Source File: ContentDefaultModal.tsx    From hub with Apache License 2.0 4 votes vote down vote up
ContentDefaultModal = (props: Props) => {
  const history = useHistory();
  const anchor = useRef<HTMLDivElement>(null);
  const [openStatus, setOpenStatus] = useState<boolean>(false);
  const [selectedItem, setSelectedItem] = useState<any | null>(null);
  const [isChangingSelectedItem, setIsChangingSelectedItem] = useState<boolean>(false);
  const [code, setCode] = useState<string | undefined>(undefined);
  const [inputValue, setInputValue] = useState<string>('');
  const [visibleFiles, setVisibleFiles] = useState<any[]>(props.files || []);
  const [currentPkgId, setCurrentPkgId] = useState<string>(props.packageId);

  const onItemChange = (file: any | null) => {
    setIsChangingSelectedItem(true);
    setSelectedItem(file);
    updateUrl(file ? file.name.toLowerCase() : undefined);
    const getContent = (): string | undefined => {
      let content: string | undefined;
      switch (props.kind) {
        case ContentDefaultModalKind.CustomResourcesDefinition:
          if (!isNull(file) && !isUndefined(file.example)) {
            content = stringify(file.example, { sortMapEntries: true });
          }
          break;
        default:
          content = file.file;
          break;
      }

      return content;
    };

    if (!isNull(file)) {
      setCode(getContent());
      if (anchor && anchor.current) {
        anchor.current.scrollIntoView({
          block: 'start',
          inline: 'nearest',
          behavior: 'smooth',
        });
      }
    } else {
      setCode(undefined);
    }
    setIsChangingSelectedItem(false);
  };

  const onChange = (e: ChangeEvent<HTMLInputElement>) => {
    e.stopPropagation();
    e.preventDefault();

    setInputValue(e.target.value);
  };

  useEffect(() => {
    const getVisibleFiles = (): any[] => {
      return props.files!.filter((file: any) => {
        const term = `${file.name} ${file.kind || ''}`.toLowerCase();
        return term.includes(inputValue.toLowerCase());
      });
    };

    const reviewActiveFile = (currentFilteredFiles: any[][]) => {
      if (currentFilteredFiles.length === 0 && !isUndefined(selectedItem)) {
        onItemChange(null);
      } else {
        if (selectedItem) {
          const activeFile = currentFilteredFiles.find((file: any) => file === selectedItem);
          if (isUndefined(activeFile)) {
            onItemChange(currentFilteredFiles[0]);
          }
        } else {
          onItemChange(currentFilteredFiles[0]);
        }
      }
    };

    if (props.files && props.files.length > 0) {
      if (inputValue === '') {
        setVisibleFiles(props.files);
        if (isUndefined(selectedItem)) {
          onItemChange(props.files[0]);
        }
      } else {
        const filteredFiles = getVisibleFiles();
        reviewActiveFile(filteredFiles);
        setVisibleFiles(filteredFiles);
      }
    }
  }, [inputValue]); /* eslint-disable-line react-hooks/exhaustive-deps */

  const updateUrl = (fileName?: string) => {
    history.replace({
      search: `?modal=${props.modalName}${fileName ? `&file=${fileName}` : ''}`,
      state: { searchUrlReferer: props.searchUrlReferer, fromStarredPage: props.fromStarredPage },
    });
  };

  const cleanUrl = () => {
    history.replace({
      search: '',
      state: { searchUrlReferer: props.searchUrlReferer, fromStarredPage: props.fromStarredPage },
    });
  };

  useEffect(() => {
    if (props.visibleModal && !openStatus && props.files && props.files.length > 0) {
      onOpenModal();
    }
  }, []); /* eslint-disable-line react-hooks/exhaustive-deps */

  useEffect(() => {
    if (props.packageId !== currentPkgId) {
      setCurrentPkgId(props.packageId);
      if (openStatus) {
        setOpenStatus(false);
      } else if (!openStatus && props.visibleModal) {
        onOpenModal();
      }
    }
  }, [props.packageId]); /* eslint-disable-line react-hooks/exhaustive-deps */

  if (isUndefined(props.files) || props.files.length === 0) return null;

  const getSelectedFileName = (): string => {
    switch (props.kind) {
      case ContentDefaultModalKind.CustomResourcesDefinition:
        return `${props.normalizedName}-${selectedItem.kind}.yaml`;
      case ContentDefaultModalKind.Rules:
        return `${props.normalizedName}-${selectedItem.name.replace('.yaml', '')}.yaml`;
      case ContentDefaultModalKind.Policy:
        return `${props.normalizedName}-${selectedItem.name}`;
    }
  };

  const onOpenModal = () => {
    if (props.files && props.files.length > 0) {
      setVisibleFiles(props.files);
      let currentActiveFile = props.files[0];
      if (props.visibleFile) {
        const visibleFile = props.files.find((file: any) => file.name.toLowerCase() === props.visibleFile);
        if (visibleFile) {
          currentActiveFile = visibleFile;
        }
      }
      onItemChange(currentActiveFile);
      setOpenStatus(true);
    } else {
      cleanUrl();
    }
  };

  const onCloseModal = () => {
    setOpenStatus(false);
    setSelectedItem(null);
    setCode(undefined);
    setInputValue('');
    cleanUrl();
  };

  return (
    <div className="mb-2">
      <div className="text-center">
        <button
          className="btn btn-outline-secondary btn-sm text-nowrap w-100"
          onClick={onOpenModal}
          aria-label={`Open ${props.title} modal`}
          disabled={isUndefined(props.files) || props.files.length === 0}
        >
          {props.btnModalContent}
        </button>
      </div>

      {openStatus && (
        <Modal
          modalDialogClassName={styles.modalDialog}
          modalClassName="h-100"
          header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>{props.title}</div>}
          onClose={onCloseModal}
          open={openStatus}
          breakPoint="md"
          footerClassName={styles.modalFooter}
        >
          <div className="h-100 mw-100">
            <div className="d-flex flex-row align-items-stretch g-0 h-100 mh-100">
              <div className="col-3 h-100 overflow-auto">
                <div className="position-relative w-100 pe-2">
                  <div className="mb-3 input-group-sm">
                    <input
                      type="text"
                      placeholder={`Search by name ${
                        props.kind === ContentDefaultModalKind.CustomResourcesDefinition ? 'or resource kind' : ''
                      }`}
                      className={`flex-grow-1 form-control ps-3 pe-4 ${styles.input}`}
                      name="contentDefaultModalInput"
                      value={inputValue}
                      onChange={onChange}
                      spellCheck="false"
                    />

                    <FaSearch className={`text-muted position-absolute ${styles.searchIcon}`} />

                    <div className="alert p-0 mt-3">
                      <small className="text-muted text-break fst-italic">
                        This package version contains <span className="fw-bold">{props.files.length}</span>{' '}
                        {FILE_TYPE[props.kind][props.files.length === 1 ? 'singular' : 'plural']}
                      </small>
                    </div>
                  </div>
                </div>

                {visibleFiles.length === 0 ? (
                  <div
                    className="alert alert-dark p-2 text-center"
                    role="alert"
                    aria-live="assertive"
                    aria-atomic="true"
                  >
                    <small className="text-muted">Sorry, no matches found</small>
                  </div>
                ) : (
                  <div className="pe-2">
                    {visibleFiles.map((file: any, index: number) => {
                      const isActive = selectedItem === file;
                      return (
                        <button
                          key={`file_${file.name}_${index}`}
                          className={classnames('btn btn-light btn-sm mb-2 text-start w-100', styles.btn, {
                            [`activeTemplate ${styles.active}`]: isActive,
                          })}
                          onClick={() => {
                            if (!isActive) {
                              onItemChange(file);
                            }
                          }}
                          aria-label={`Show ${props.title} ${file.name}`}
                          aria-pressed={isActive}
                        >
                          <div className="d-flex flex-column align-self-center">
                            {(() => {
                              switch (props.kind) {
                                case ContentDefaultModalKind.CustomResourcesDefinition:
                                  const resource = file as CustomResourcesDefinition;
                                  return (
                                    <>
                                      <div className="d-flex flex-row align-items-baseline my-1">
                                        <div className={styles.legend}>
                                          <small className="text-muted text-uppercase">Kind:</small>
                                        </div>
                                        <span className={`text-truncate border fw-bold ${styles.label}`}>
                                          {resource.kind}
                                        </span>
                                      </div>

                                      <div className="d-flex flex-row align-items-baseline mb-1">
                                        <div className={styles.legend}>
                                          <small className="text-muted text-uppercase">Version:</small>
                                        </div>
                                        <div className={`text-truncate ${styles.btnItemContent}`}>
                                          {resource.version}
                                        </div>
                                      </div>
                                    </>
                                  );

                                default:
                                  return (
                                    <div className="d-flex flex-row align-items-baseline mb-1">
                                      <div>
                                        <small className="text-muted text-uppercase me-2">Name:</small>
                                      </div>
                                      <div className={`text-truncate ${styles.btnItemContent}`}>{file.name}</div>
                                    </div>
                                  );
                              }
                            })()}
                          </div>
                        </button>
                      );
                    })}
                  </div>
                )}
              </div>

              <div className="col-9 ps-3 h-100">
                <div className={`position-relative h-100 mh-100 border ${styles.templateWrapper}`}>
                  {isChangingSelectedItem && <Loading />}

                  <div className="d-flex flex-column h-100">
                    {!isNull(selectedItem) && (
                      <>
                        {(() => {
                          switch (props.kind) {
                            case ContentDefaultModalKind.CustomResourcesDefinition:
                              return (
                                <div className={`p-3 border-bottom ${styles.extraInfo}`}>
                                  <div className="h6 fw-bold">{selectedItem.displayName || selectedItem.name}</div>
                                  <div className="d-flex flex-row align-items-baseline mb-1">
                                    <div className={styles.legend}>
                                      <small className="text-muted text-uppercase">Name:</small>
                                    </div>
                                    <div className={`text-truncate ${styles.btnItemContent}`}>{selectedItem.name}</div>
                                  </div>

                                  <div className="d-flex flex-row align-items-baseline mb-1">
                                    <div className={styles.legend}>
                                      <small className="text-muted text-uppercase">Description:</small>
                                    </div>
                                    <div className={styles.btnItemContent}>
                                      {selectedItem.description.replace(/\n/g, ' ')}
                                    </div>
                                  </div>
                                </div>
                              );

                            default:
                              return null;
                          }
                        })()}
                      </>
                    )}
                    <div className="position-relative flex-grow-1 overflow-hidden h-100">
                      {visibleFiles.length > 0 && (
                        <>
                          {code && !isNull(selectedItem) ? (
                            <>
                              <BlockCodeButtons filename={getSelectedFileName()} content={code} />
                              <div className={`position-relative overflow-auto h-100 ${styles.fileWrapper}`}>
                                <div className={`position-absolute ${styles.anchor}`} ref={anchor} />

                                <SyntaxHighlighter
                                  language={props.language}
                                  style={docco}
                                  customStyle={{
                                    backgroundColor: 'transparent',
                                    padding: '1.5rem',
                                    lineHeight: '1.25rem',
                                    marginBottom: '0',
                                    height: '100%',
                                    fontSize: '80%',
                                    overflow: 'initial',
                                    color: '#636a6e',
                                  }}
                                  lineNumberStyle={{
                                    color: 'var(--color-black-25)',
                                    marginRight: '5px',
                                    fontSize: '0.8rem',
                                  }}
                                  showLineNumbers
                                >
                                  {code}
                                </SyntaxHighlighter>
                              </div>
                            </>
                          ) : (
                            <div className="fst-italic d-flex align-items-center justify-content-center h-100 h3">
                              No example provided
                            </div>
                          )}
                        </>
                      )}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </Modal>
      )}
    </div>
  );
}